2014-09-02 2 views
2

뮤텍스에 대한 인터넷에서 많은 자습서를 찾았습니다. 그런 다음 내 자신의 샘플을 작성하려고했습니다. 다음 코드 스 니펫을 살펴보십시오.원하는 순서대로 번호를 인쇄하는 방법

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 

func main() { 

    thread := new(sync.Mutex) 
    y := 0 

    for i := 0; i < 10; i++ { 
     go func() { 
      y = i 
      thread.Lock() 
      fmt.Println(y) 
      thread.Unlock() 
     }() 
    } 

    time.Sleep(100000) 

} 

출력이 10인데 대상은 1, 2, 3, 4 ... 10입니다. 어떻게해야합니까? 아니면 내 표본이 말이 안 되니?

+0

당신이 받아 들인 답안과 답은 뮤텍스를 사용하는 샘플이 아닌지 * 유의하십시오. 왜냐하면 여기서 뮤텍스는 아무런 효과가 없기 때문입니다. – JimB

답변

2

문제는 함수 종료가 외부 범위 변수 i 에 바인딩되어 있고 루프 중에 i이 변경된다는 점입니다.

http://play.golang.org/p/ylTENWeuEl

: i의 값이 10

이것을 해결 양방향있다이다 (루프가 완료되면 대부분) 루틴이 실행되며, 첫 번째는 각 루프에 새로운 변수를 생성 할 때

http://play.golang.org/p/DKd12-VNSk

:
for i := 0; i < 10; i++ { 
    y := i 
    go func() { 
     thread.Lock() 
     fmt.Println(y) 
     thread.Unlock() 
    }() 
} 

또는 기능에 직접 고정 값을 전달하여

+0

이것은 결과의 정렬을 보장하지 않지만 – JimB

+0

은 OP가 명시 적으로 정렬 된 결과를 요구하지 않았습니다. 그런 다음 goroutines 필요 없음, 그냥 값을 인쇄하십시오 :) – fabrizioM

+0

"... 원하는 순서대로";) (나는 처음에 너무 그것을 놓쳤습니다) – JimB

1

시도 : 여기

for i := 0; i < 10; i++ { 
    go func(j int) { 
     thread.Lock() 
     fmt.Println(j) 
     thread.Unlock() 
    }(i) 
} 

why입니다.

+1

이것은 결과의 순서를 보증하지 않습니다. http://play.golang.org/p/He8llc9lj_. – peterSO

+0

@peterSO 네, 맞습니다. –

2

귀하의 예는 의미가 없습니다. 간단하게 쓰기 :

package main 

import (
    "fmt" 
) 

func main() { 
    for i := 0; i < 10; i++ { 
     fmt.Print(i, " ") 
    } 
    fmt.Println() 
} 

출력 :

0 1 2 3 4 5 6 7 8 9 

을 프로그램의 버그를 수정 한 후에는 사용 goroutines가 정렬 된 결과를 제공하지 않을 것임을 쉽게 알 수있다.

package main 

import (
    "fmt" 
    "runtime" 
    "sync" 
    "time" 
) 

func main() { 
    runtime.GOMAXPROCS(runtime.NumCPU() + 2) 
    thread := new(sync.Mutex) 
    for i := 0; i < 10; i++ { 
     y := i 
     go func() { 
      thread.Lock() 
      fmt.Print(y, " ") 
      thread.Unlock() 
     }() 
    } 
    time.Sleep(time.Second) 
    fmt.Println() 
} 

출력 :

1 0 5 6 2 7 8 9 3 4 

놀이터 :

peterSO 이미 지적 단순히 순서대로 인쇄 할 경우, 동시성 (루틴으로 이동)으로

http://play.golang.org/p/FQdrL3z-hR

1

뮤텍스은 때로 믿을 수 필요한 항목 :

for i := 0; i < 10; i++ { 
     fmt.Println(i) 
} 

그러나 계산을 동시에 수행하고 원하는 순서로 결과를 인쇄하려면 채널을 사용하여 해결하고 주 루틴에서 순서대로 인쇄하거나 sync.Cond을 사용하여 결과를 인쇄 할 수 있습니다

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 
func main() { 

    var wg sync.WaitGroup 

    c := sync.NewCond(new(sync.Mutex)) 
    var printed int 

    for i := 0; i < 10; i++ { 
     wg.Add(1) 
     go func(y int) { 
      // Do some costly calculation that cakes y*y%10 milliseconds 
      time.Sleep(time.Duration(y*y%10) * time.Millisecond) 

      c.L.Lock() 
      // Wait in a loop til it is this goroutine's turn 
      for printed != y { 
       c.Wait() 
      } 
      fmt.Printf("%d ", y) 
      printed++ 
      c.L.Unlock() 

      // Tell the waiting routines to check if it is their turn 
      c.Broadcast() 
      wg.Done() 
     }(i) 
    } 

    wg.Wait() 
} 

출력 :

0 1 2 3 4 5 6 7 8 9 

운동장 :http://play.golang.org/p/k7tUfKPRxW

,536 아래 예

time.Sleep(time.Second) 대신 sync.WaitGroup을 사용하여 main이 조기에 종료되지 않도록했습니다. 그래도 sync.Cond 솔루션에는 필요하지 않습니다.

관련 문제