lock和wait+signal
2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
lock和wait+signal
在編程中,我們經(jīng)常使用多線程來提升性能,所以這就涉及到互斥和同步的問題了。而在編程中,我們一般都是通過如下方式來完成多線程的互斥和同步:
- lock | unlock
- signal + wait(timeout)
- join
- sleep
C語言
在Linux C編程中,我們通常使用pthread類庫來完成跨平臺的多線程控制,如下是幾個常用的API:
- pthread_mutex_lock():占有互斥鎖(阻塞操作)
- pthread_mutex_unlock(): 釋放互斥鎖
- pthread_cond_signal(): 喚醒第一個調(diào)用pthread_cond_wait()而進入睡眠的線程
- pthread_cond_wait(): 等待條件變量的特殊條件發(fā)生
- pthread_cond_timedwait():等待條件變量的特殊條件發(fā)生或者timeout
- pthread_join():阻塞當(dāng)前的線程,直到另外一個線程運行結(jié)束
- sleep() : 休眠固定時間,不過這個API是Linux原生提供,不能跨平臺。
注意:**pthread類庫是glibc(絕大多數(shù)Linux平臺標(biāo)準(zhǔn)C庫。)的一部分。這些功能都是通過中斷號進入內(nèi)核來完成的,而非僅僅做了Linux兼容API。**具體可見 glibc-2.23\sysdeps\nacl\nacl-interface-list.h ,聲明wait(timeout)功能中斷號文件。
Java
在Java中,多線程的控制已經(jīng)是一個統(tǒng)一標(biāo)準(zhǔn)了,一般都是通過Java原生API或者JUC來實現(xiàn)并發(fā)控制。這里來說說原生的API:
- synchronized : 實現(xiàn)了lock 和 unlock的功能
- Object#wait : 等待信號發(fā)生,并且可以實現(xiàn)超時等待
- Object#notify : 通知信號發(fā)生
- Object#notifyAll :通知信號發(fā)生
- Thread#join :阻塞當(dāng)前的線程,直到另外一個線程運行結(jié)束
- Thread#sleep : 休眠固定時間
通過這些API,我們基本上能實現(xiàn)Java的多線程并發(fā)控制,當(dāng)然了可以使用最新的JUC并發(fā)庫的API。而這些API底層也是可以通過pthread這個C庫來實現(xiàn)。
示例-Timer
Java中Timer的實現(xiàn)原理就是通過 wait 和 notify 以及 synchronized 來實現(xiàn)的:
Timer timer = new Timer(); timer.schedule(new TimerTask() {@Overridepublic void run() {} }, 1000);其實,Timer持有TimerImpl,其實Impl就是一個Thread實現(xiàn),它一直阻塞等待task的到來,見run代碼:
public void run() {while (true) {TimerTask task;synchronized (this) {// need to check cancelled inside the synchronized blockif (cancelled) {return;}//等待任務(wù)if (tasks.isEmpty()) {if (finished) {return;}// no tasks scheduled -- sleep until any task appeartry {//等待任務(wù)加入后,會通過notify來通知它可以運行this.wait();} catch (InterruptedException ignored) {}continue;}....if (timeToSleep > 0) {// sleep!try {//延遲執(zhí)行代碼this.wait(timeToSleep);} catch (InterruptedException ignored) {}continue;}// no sleep is necessary before launching the task...}...try {//具體執(zhí)行任務(wù)task.run();taskCompletedNormally = true;} finally {...}} }可以看到TimerImpl的run代碼會通過wait來阻塞等待任務(wù)加入queue,然后通過notify告知它可以運行task。timer#schedule最后會調(diào)用TimerImpl#insertTask,具體代碼如下:
private void insertTask(TimerTask newTask) {// callers are synchronizedtasks.insert(newTask);this.notify(); }**所以任務(wù)加入隊列后,通過notify來告知阻塞在等待任務(wù)的線程(TimerImpl#run)。**這樣子就實現(xiàn)了Timer的功能了,并且通過wait(timeout)實現(xiàn)了delay的功能。
總結(jié)
多線程的控制,其實大多都是依賴:
- lock
- signal + wait
這兩種類型的API來完成并發(fā)控制。
而在此基礎(chǔ)上,我們可以實現(xiàn)各種各樣的多線程并發(fā)控制,比如說:MQ,CountDownLatch等。
轉(zhuǎn)載于:https://my.oschina.net/darkgem/blog/660784
總結(jié)
以上是生活随笔為你收集整理的lock和wait+signal的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 红楼梦任选人物读后感
- 下一篇: hive UDF函数