Leetcode concurrency #1117 Building H2O (in golang)
今天的題目掙扎了一下,主要是對golang沒這麼熟,花了點時間試誤,最後還是選擇土法煉鋼的解。前幾天,我們試過同步處理中的Event和Lock,今天依然是解同步處理的問題,這次嘗試用號誌來解決。
題目解析:給一串字串僅包含H和O兩種字母,而且H的數量一定要是O的兩倍。接著起一堆thread,每個thread只可能會有印出H或印出O這兩個功能,目的是要將輸入的字串整理成HHOHHOHHO...的序列。
這題的難處在於一狗票的thread同時跑起來,要能夠快速知道甚麼時候開始印H又哪時候要印O。看到題目的第一直覺就是semaphore,只要起兩個semaphore,一個設2來決定H、另一個也設2來決定O就可以了。但是,碰到幾個問題:首當其衝的是,golang的sync裡沒有semaphore的實作,必須使用golang.org/x/sync/semaphore下的Weighted;另一個問題是,在這個package底下實作的Release不會空等,在沒有Acquire足夠數量的前題下,直接使用Release就panic。
semaphore: released more than held
正常的流程是H thread,先Acquire(H1),若是可行,就印出H然後,Acquire(O1)來通知O開始跑;而O thread的流程是,先Release(O2),若是可行,就印出O並且Release(H2)來告訴下一輪的H。但用原來的Release,O在第一次Release(O2)就會炸。因此我把整個package拷貝過來,並且修改Release的作法,做成類似自旋鎖的概念。
中間一大段拷貝可以略過不用看,幾乎都和原來的一樣,除了Release被我大改之外。當Release的問題解決之後,其實解法就和剛剛描述的流程一樣,從code可以很清楚的看到hydrogen和oxygen的實作都很簡單。