Golang中与Java的synchronized()块等效的是什么?

huangapple go评论99阅读模式
英文:

what is the golang equivalent of a Java synchronized() block?

问题

Java提供了一种非常方便的习语来同步代码的关键部分:

  1. synchronized(someObject) {
  2. // 独自完成一些非常重要的事情,没有人打扰我
  3. }

或者

  1. public synchronized void doSomething() {
  2. // ...
  3. }

Go语言的等效方式是什么?

(快速搜索结果显示:<a href="http://golang.org/pkg/sync/">golang.org/pkg/sync/</a> - 这似乎(也许我错了)对于一般用途来说有点太底层。)

(为什么我关心这个的例子:我需要通过通道向多个监听器发送消息。通道为数据提供了一个良好的传输通道,而无需同步任何内容,但是当通道被添加或删除时,我需要修改通道列表,这可能随时发生,必须能够处理并发。)

英文:

Java provides a very convenient idiom for synchronizing critical portions of code:

  1. synchronized(someObject) {
  2. // do something really important all by myself with nobody bothering me
  3. }

Or

  1. public synchronized void doSomething() {
  2. // ...
  3. }

What is the go equivalent?

(A quick search reveals: <a href="http://golang.org/pkg/sync/">golang.org/pkg/sync/</a> - which seems (maybe I'm wrong) a bit too low level for general use.)

(Example of why I care about this: I need to send a message to multiple listeners via channels. Channels provide a good conduit for the data without having to synchronize anything, but when channels are added or removed I need to modify the list of channels, which might happen at any time must be able to deal with concurrency.)

答案1

得分: 22

sync.Mutex 是一种互斥锁,它可以提供类似于 Java 中的 synchronized 关键字的功能(除了 Java 中的锁提供了可重入的互斥)。

  1. synchronized(someObject) {
  2. //
  3. }

等价于:

  1. var l sync.Mutex
  2. l.Lock()
  3. //
  4. l.Unlock()
英文:

sync.Mutex is a mutual exclusion lock, it can provide a similar functionality to the synchronized java key-word (except that locks in java provide reentrant mutual exclusion) :

  1. synchronized(someObject) {
  2. //
  3. }

Is equivalent to :

  1. var l sync.Mutex
  2. l.Lock()
  3. //
  4. l.Unlock()

答案2

得分: 16

扩展tarrsalah的答案。

您可以将sync.Mutex添加到您的对象中,以便可以直接对其进行锁定和解锁。

  1. type MyObject struct{
  2. Number int
  3. sync.Mutex
  4. }
  5. func (m *MyObject)Increment(){
  6. m.Lock()
  7. defer m.Unlock()
  8. m.Number++
  9. }

延迟的命令将在函数末尾运行,这样您就知道它既被锁定又被解锁,在更大的函数中也适用。

英文:

to extend off tarrsalah's answer.

You can add sync.Mutex to your object, allowing them to be directly locked and unlocked.

  1. type MyObject struct{
  2. Number int
  3. sync.Mutex
  4. }
  5. func (m *MyObject)Increment(){
  6. m.Lock()
  7. defer m.Unlock()
  8. m.Number++
  9. }

Defer'd commands will run at the end of the function, this way you know it gets both locked and unlocked, in bigger functions.

答案3

得分: 9

使用互斥锁的另一种解决方案是使用通道来进行监听器的通信。

以下是一个完整的示例,代码的重点在于FanOuter函数。

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. type Message int
  7. type ListenerUpdate struct {
  8. Add bool
  9. Listener chan Message
  10. }
  11. // FanOuter维护监听器,并将来自msgc的消息转发给每个监听器。listc上的更新可以添加或删除监听器。
  12. func FanOuter(msgc chan Message, listc chan ListenerUpdate) {
  13. lstrs := map[chan Message]struct{}{}
  14. for {
  15. select {
  16. case m := <-msgc:
  17. for k := range lstrs {
  18. k <- m
  19. }
  20. case lup := <-listc:
  21. if lup.Add {
  22. lstrs[lup.Listener] = struct{}{}
  23. } else {
  24. delete(lstrs, lup.Listener)
  25. }
  26. }
  27. }
  28. }
  29. func main() {
  30. msgc := make(chan Message)
  31. listc := make(chan ListenerUpdate)
  32. go FanOuter(msgc, listc)
  33. // 慢慢添加监听器,然后慢慢删除它们。
  34. go func() {
  35. chans := make([]chan Message, 10)
  36. // 添加监听器。
  37. for i := range chans {
  38. chans[i] = make(chan Message)
  39. // 监听器打印其ID和接收到的任何消息。
  40. go func(i int, c chan Message) {
  41. for {
  42. m := <-c
  43. fmt.Printf("%d received %d\n", i, m)
  44. }
  45. }(i, chans[i])
  46. listc <- ListenerUpdate{true, chans[i]}
  47. time.Sleep(300 * time.Millisecond)
  48. }
  49. // 删除监听器。
  50. for i := range chans {
  51. listc <- ListenerUpdate{false, chans[i]}
  52. time.Sleep(300 * time.Millisecond)
  53. }
  54. }()
  55. // 每秒向fanouter发送一条消息。
  56. for i := 0; i < 10; i++ {
  57. fmt.Println("About to send ", i)
  58. msgc <- Message(i)
  59. time.Sleep(1 * time.Second)
  60. }
  61. }

希望对你有帮助!

英文:

A different solution to using a mutex is to use a channel to communicate listener changes.

A full example in this style looks like this. The interesting code is in FanOuter.

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;time&quot;
  5. )
  6. type Message int
  7. type ListenerUpdate struct {
  8. Add bool
  9. Listener chan Message
  10. }
  11. // FanOuter maintains listeners, and forwards messages from msgc
  12. // to each of them. Updates on listc can add or remove a listener.
  13. func FanOuter(msgc chan Message, listc chan ListenerUpdate) {
  14. lstrs := map[chan Message]struct{}{}
  15. for {
  16. select {
  17. case m := &lt;-msgc:
  18. for k := range lstrs {
  19. k &lt;- m
  20. }
  21. case lup := &lt;-listc:
  22. if lup.Add {
  23. lstrs[lup.Listener] = struct{}{}
  24. } else {
  25. delete(lstrs, lup.Listener)
  26. }
  27. }
  28. }
  29. }
  30. func main() {
  31. msgc := make(chan Message)
  32. listc := make(chan ListenerUpdate)
  33. go FanOuter(msgc, listc)
  34. // Slowly add listeners, then slowly remove them.
  35. go func() {
  36. chans := make([]chan Message, 10)
  37. // Adding listeners.
  38. for i := range chans {
  39. chans[i] = make(chan Message)
  40. // A listener prints its id and any messages received.
  41. go func(i int, c chan Message) {
  42. for {
  43. m := &lt;-c
  44. fmt.Printf(&quot;%d received %d\n&quot;, i, m)
  45. }
  46. }(i, chans[i])
  47. listc &lt;- ListenerUpdate{true, chans[i]}
  48. time.Sleep(300 * time.Millisecond)
  49. }
  50. // Removing listeners.
  51. for i := range chans {
  52. listc &lt;- ListenerUpdate{false, chans[i]}
  53. time.Sleep(300 * time.Millisecond)
  54. }
  55. }()
  56. // Every second send a message to the fanouter.
  57. for i := 0; i &lt; 10; i++ {
  58. fmt.Println(&quot;About to send &quot;, i)
  59. msgc &lt;- Message(i)
  60. time.Sleep(1 * time.Second)
  61. }
  62. }

huangapple
  • 本文由 发表于 2013年9月19日 03:20:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/18880575.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定