Single-piece mode--golang implementation

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

The single-piece mode is more common, is a design pattern of creation, and unlike the factory model, he can only create one instance. He has a lot of applications, such as MySQL can only have one instance of this count.

The single-piece mode can be divided into two types: support concurrency and not support concurrency. But the concurrency of this is very simple, full street Golang implementation of the single-piece mode is the case.

Common single-piece mode

package singletonimport ("fmt")var _self *Singletontype Singleton struct {Name string}func Instance() *Singleton {if _self == nil {_self = new(Singleton)return _self}return _self}func (o *Singleton) SetName(s string) {_self.Name = s}func (o *Singleton) GetName() {fmt.Println("Name:", _self.Name)}

Supporting concurrent single-piece mode is also not difficult, on this basis add a called Double Check processing. I was asked this when I went to the net interview, so this thing has always been remembered.

Single-piece mode in the case of concurrency, the above code is problematic, it may be created several times, the above example adds a log:

var _self *Singletontype Singleton struct {Name string}func NewInstance(name string) *Singleton {fmt.Println("Create instance", name)time.Sleep(4 * time.Second)_self.Name = namereturn _self}func Instance(name string) *Singleton {if _self.Name == "" {return NewInstance(name)}return _self}func main() {_self = new(Singleton)go Instance("cyeam")go Instance("bryce")time.Sleep(10 * time.Second)fmt.Println(_self.Name)}

The results are as follows. The example adds parameters to the instantiation function, which makes it easy to determine the number and result of the instantiation. From the results shown below, the unlocked single-piece mode creates two instances, and the second creates an instance that overrides the first one created.

Create instance cyeamCreate instance brycebryce

Support for concurrent single-piece mode

To ensure that only one instance is created in parallel invocation, a lock is required to ensure serial creation. The simple and rude way is to Instance() lock all the methods directly.

var _self *Singletontype Singleton struct {Name stringsync.Mutex}func NewInstance(name string) *Singleton {fmt.Println("Create instance", name)time.Sleep(4 * time.Second)_self.Name = namereturn _self}func Instance(name string) *Singleton {_self.Mutex.Lock()defer _self.Mutex.Unlock()if _self.Name == "" {return NewInstance(name)}return _self}func main() {_self = new(Singleton)_self.Mutex = sync.Mutex{}go Instance("cyeam")go Instance("bryce")time.Sleep(10 * time.Second)fmt.Println(_self.Name)}

Simple and brutal lock-up can be found to solve the problem of multiple concurrent creation. However, the entire creation process becomes a serial call. For example, there are 1000 create requests, as long as you create an instance, the remaining 999 times there is absolutely no need to lock, directly to the first instance created by the return of a good. And this way of writing will cause every time with a lock access, affecting the speed.

Create instance cyeamcyeam

Then the above idea, we can not for this function as a whole lock, when the creation of the lock can be.

func Instance(name string) *Singleton {if _self.Name == "" {_self.Mutex.Lock()defer _self.Mutex.Unlock()return NewInstance(name)}return _self}

After judging that the confirmation object is empty, start creating the object with the following result:

Create instance cyeamCreate instance brycebryce

Although the lock has been added, you can see that the object is still created two times. If two concurrent creation calls, at this time if _self.Name == "" the call is also executed at the same time, naturally true , and then, although there is a lock, but also the serial to create the object, the outside if in the case of no lock is invalid.

At this time, you need a Double check, in the lock and then a check empty.

func Instance(name string) *Singleton {if _self.Name == "" {_self.Mutex.Lock()defer _self.Mutex.Unlock()if _self.Name == "" {return NewInstance(name)}}return _self}

The results are as follows. As a result, both efficiency and support for concurrency can be well supported.

Create instance cyeamcyeam

These are written in the traditional wording, for the general language use, for my big Golang, there is a simpler implementation.

import ("fmt""sync""time")var _self *Singletontype Singleton struct {Name stringsync.Once}func NewInstance(name string) *Singleton {fmt.Println("Create instance", name)time.Sleep(4 * time.Second)_self.Name = namereturn _self}func Instance(name string) *Singleton {if _self.Name == "" {_self.Once.Do(func() { NewInstance(name) })}return _self}func main() {_self = new(Singleton)_self.Once = sync.Once{}go Instance("cyeam")go Instance("bryce")time.Sleep(10 * time.Second)fmt.Println(_self.Name)}

Please refer to the complete source code in this article.

Reference documents

    1. Design mode (2)-Singleton single-piece mode-shltsh

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.