[Go language] innocent Goroutine

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. Introduction:This article is mainly aimed at some of Goroutine's "accusations" put forward my own views, in particular, a blog article on the Xuan Pulse Blade "on the use of goroutine in the go language," put forward several goroutine crimes. In fact, Goroutine does have an increase in procedural complexity that can lead to problems, especially deadlocks, but in other cases, I do not think that Goroutine is directly responsible.
The following is a discussion on the use of goroutine in the go language. One by one put forward my point of view. The first accusation: Goroutine is not safe to pass the pointer.Original: Fun Main () { Request: = Request. Newrequest ()//Here The Newrequest () is passed back to a typerequest pointer GOSAVEREQUESTTOREDIS1 (Request) GOSAVEREUQESTTOREDIS2 (Request) Select{}}func SaveRequestToRedis1 (request*request) { ... Request. Tousers = []int{1,2,3}//Here is an assignment operation that modifies the data structure that the request points to ... Redis. Save (Request) return} What's wrong with this? SaveRequestToRedis1 and SaveReuqestToRedis2 Two goroutine modify the same shared data structure, but because the execution of the routine is unordered, we cannot guarantee the request. Tousers settings and Redis.save () are atomic operations, which can cause a bug that actually stores redis data errors. Well, you can say that this Saverequesttoredis function is implemented with a problem and is not considered to be called using Goroutine. Think again, this saverequesttoredis concrete implementation is no problem, it should not consider how the upper layer is how to use it. That's my goroutine. The use of the problem, the main routine in the opening of a routine did not confirm that the routine in any of the code has changed the main routine data. Yes, the main routine really need to think about this situation. But according to this idea, so? The main goroutine need to read each line of code in the sub-routine when enabling Goroutine to determine if there are any modifications to the shared data?? This is in the actual project development process is how to reduce the development speed of one thing Ah!
My point of view: 1. Functions and callers must follow a certain specification or convention directly. This convention includes: 1) function signature. This can be guaranteed by the compiler in a strongly typed programming language. 2) semantics. Is that the caller is going to invoke the function according to the purpose of the function, and the function must achieve its own purpose. If a read function, read actually executes a write operation, is a semantic error. 3) Access control with data, including read-Write permissions and thread (goroutine) security. For example, the parameter or the data returned by who is responsible for the control, the function is not able to write parameters to point to the data and so on. Especially in the function exposed by the package, the permission description of the data is particularly important. An example is bytes. The Buffer.next method, which is clearly stated in the documentation, is that the data it returns is valid only until the next read and write operation. 2. In view of the above example, according to the 1 principle, it is found that the calling convention between SAVEREQUESTTOREDIS1 and the caller is not clear. If the calling convention indicates that the data pointed to by the parameter is modified, it is the caller's problem, and if the calling convention indicates that the data pointed to by the parameter is not modified, it is the function implementation problem. 3. Therefore, the problem in this example is actually a question that the calling convention is unclear or not complied with, and Goroutine is innocent here.
second allegation: Goroutine increases the risk factor for the functionIn the original: it is not safe to pass pointers to a go function as stated above. How can you guarantee that the function you want to invoke does not use go inside the function implementation? There is no way to determine if you do not look at the body of the function in detail. For example, we will change the typical example above to the Func main () { Request: = Request. Newrequest () SAVEREQUESTTOREDIS1 (Request) SAVEREQUESTTOREDIS2 (Request) select{}} We're not using concurrency, so we're not going to have this problem? Chase into the function inside, dumbfounded: Func saveReqeustToRedis1 (request*request) {
... go func () {
...
..
request. Tousers = []{1,2,3}
...
.
Redis. Save (Request)
}
I'm going to take a goroutine and change the object that the request pointer is pointing to. There's been a mistake here. Well, this problem cannot be avoided if the function is called without looking at the actual implementation within the function. So, what? So, from the worst-case perspective, every calling function is theoretically unsafe! Imagine that this calling function is written by someone who is not a development group, but uses the third-party open source code on the network ... It's really impossible to imagine how long it will take to find this bug.
My point of view: 1. In fact, the problem is similar to the first one, and the actual problem is unclear about the permissions of the data and the Goroutine security, except that it is now the function that calls the other sub-functions itself into the caller. 2. For Goroutine Security Example: Database/sql. STMT's documentation explains that "STMT is safefor concurrent use by multiple Goroutines". 3. What about using third-party libraries online? My point is that if its interface documentation is not related to the specification of the contract, it is recommended that such a library is not used, or the risk is too great. In fact, the quality of the library includes not only the quality of the code but also the quality of the document.
Third allegation: Goroutine's abuse trapOriginal: Func main () {
gosaverequesttoredises (Request)
}func saverequesttoredieses (request*request) {
for _, Redis: = Range redises{
Goredis.saverequesttoredis (Request)
}
}func Saverequesttoredis (request*request) {
..... go func () {
request. Tousers = []{1,2,3}
...
..
Redis. Save (Request)
}()
It's amazing that go is everywhere, like blinking and popping up. This is the abuse of go, everywhere see go, but it is not very clear, where to use go? Why use go? Is goroutine really going to be an efficient upgrade? The concurrency of the C language is more complex and cumbersome than the concurrency of the go language, so we think before we use it, consider the benefits and disadvantages of using concurrency. Where's go? Almost no.
My point of view: 1. For a function exposed by the package, the calling convention of the function must be explicitly stated in the document (note). The Go standard library is a good example. 2. For functions inside the package, there is no need to explicitly write out the calling convention. If multiple people develop the same package, it is the responsibility of the developer to understand the default convention of the called function (by looking at the function implementation or a simple convention description). 3. The use of goroutine is not a problem at all with respect to function conventions. For example, suppose you want to implement a sort function, the contract is thread insecure, that is, the same sequence is not allowed to be sorted in more than one goroutine. But we can still use goroutine:func sort (numbers []int) inside the function {
var wg sync. Waitgroupfor I: = 0; I < 5;i++ {
WG. ADD (1)
go func () {
//Sort sub-array
WG. Done ()
} ()
}WG. Wait ()//merge sub-array
}
Conclusion:1. Some problems that appear to be caused by goroutine should not be attributed to Goroutine, which may be caused by non-adherence to the function calling convention, even if the function calling convention is not adhered to in C + + +. The export function of 2.packge specifically requires the explicit function calling convention, otherwise it will cause the caller to misuse, and the PACKGE internal function contract requires the developer to control it (analogous to the developer's responsibility for the intrinsic functions of the class in C + +). 3.goroutine can cause problems that tend to occur in multiple threads such as deadlock waits. This can be a good design and a good code framework to reduce the risk of problems, strengthening code review is also an important measure.
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.