1. 程式人生 > >POSIX執行緒操作,轉的有點亂,將就記錄一下

POSIX執行緒操作,轉的有點亂,將就記錄一下

Posix執行緒程式設計指南(3)   


  
內容:

一. 互斥鎖
二. 條件變數
三. 訊號燈
四. 非同步訊號
五. 其他同步方式
關於作者


相關內容:

(1) 執行緒建立與取消 
(2) 執行緒私有資料 




執行緒同步
楊沙洲([email protected])
2001 年 10 月

這是一個關於Posix執行緒程式設計的專欄。作者在闡明概念的基礎上,將向您詳細講述Posix執行緒庫API。本文是第三篇,將向您講述執行緒同步。
一.互斥鎖
儘管在Posix Thread中同樣可以使用IPC的訊號量機制來實現互斥鎖mutex功能,但顯然semphore的功能過於強大了,在Posix Thread中定義了另外一套專門用於執行緒同步的mutex函式。

1. 建立和銷燬
有兩種方法建立互斥鎖,靜態方式和動態方式。POSIX定義了一個巨集PTHREAD_MUTEX_INITIALIZER來靜態初始化互斥鎖,方法如下:
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
在LinuxThreads實現中,pthread_mutex_t是一個結構,而PTHREAD_MUTEX_INITIALIZER則是一個結構常量。

動態方式是採用pthread_mutex_init()函式來初始化互斥鎖,API定義如下:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
其中mutexattr用於指定互斥鎖屬性(見下),如果為NULL則使用預設屬性。

pthread_mutex_destroy()用於登出一個互斥鎖,API定義如下:
int pthread_mutex_destroy(pthread_mutex_t *mutex)
銷燬一個互斥鎖即意味著釋放它所佔用的資源,且要求鎖當前處於開放狀態。由於在Linux中,互斥鎖並不佔用任何資源,因此LinuxThreads中的pthread_mutex_destroy()除了檢查鎖狀態以外(鎖定狀態則返回EBUSY)沒有其他動作。

2. 互斥鎖屬性
互斥鎖的屬性在建立鎖的時候指定,在LinuxThreads實現中僅有一個鎖型別屬性,不同的鎖型別在試圖對一個已經被鎖定的互斥鎖加鎖時表現不同。當前(glibc2.2.3,linuxthreads0.9)有四個值可供選擇:

PTHREAD_MUTEX_TIMED_NP,這是預設值,也就是普通鎖。當一個執行緒加鎖以後,其餘請求鎖的執行緒將形成一個等待佇列,並在解鎖後按優先順序獲得鎖。這種鎖策略保證了資源分配的公平性。
PTHREAD_MUTEX_RECURSIVE_NP,巢狀鎖,允許同一個執行緒對同一個鎖成功獲得多次,並通過多次unlock解鎖。如果是不同執行緒請求,則在加鎖執行緒解鎖時重新競爭。
PTHREAD_MUTEX_ERRORCHECK_NP,檢錯鎖,如果同一個執行緒請求同一個鎖,則返回EDEADLK,否則與PTHREAD_MUTEX_TIMED_NP型別動作相同。這樣就保證當不允許多次加鎖時不會出現最簡單情況下的死鎖。
PTHREAD_MUTEX_ADAPTIVE_NP,適應鎖,動作最簡單的鎖型別,僅等待解鎖後重新競爭。



3. 鎖操作
鎖操作主要包括加鎖pthread_mutex_lock()、解鎖pthread_mutex_unlock()和測試加鎖pthread_mutex_trylock()三個,不論哪種型別的鎖,都不可能被兩個不同的執行緒同時得到,而必須等待解鎖。對於普通鎖和適應鎖型別,解鎖者可以是同進程內任何執行緒;而檢錯鎖則必須由加鎖者解鎖才有效,否則返回EPERM;對於巢狀鎖,文件和實現要求必須由加鎖者解鎖,但實驗結果表明並沒有這種限制,這個不同目前還沒有得到解釋。在同一程序中的執行緒,如果加鎖後沒有解鎖,則任何其他執行緒都無法再獲得鎖。

int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)

pthread_mutex_trylock()語義與pthread_mutex_lock()類似,不同的是在鎖已經被佔據時返回EBUSY而不是掛起等待。

4. 其他
POSIX執行緒鎖機制的Linux實現都不是取消點,因此,延遲取消型別的執行緒不會因收到取消訊號而離開加鎖等待。值得注意的是,如果執行緒在加鎖後解鎖前被取消,鎖將永遠保持鎖定狀態,因此如果在關鍵區段內有取消點存在,或者設定了非同步取消型別,則必須在退出回撥函式中解鎖。

這個鎖機制同時也不是非同步訊號安全的,也就是說,不應該在訊號處理過程中使用互斥鎖,否則容易造成死鎖。

二.條件變數
條件變數是利用執行緒間共享的全域性變數進行同步的一種機制,主要包括兩個動作:一個執行緒等待"條件變數的條件成立"而掛起;另一個執行緒使"條件成立"(給出條件成立訊號)。為了防止競爭,條件變數的使用總是和一個互斥鎖結合在一起。

1. 建立和登出
條件變數和互斥鎖一樣,都有靜態動態兩種建立方式,靜態方式使用PTHREAD_COND_INITIALIZER常量,如下:
pthread_cond_t cond=PTHREAD_COND_INITIALIZER

動態方式呼叫pthread_cond_init()函式,API定義如下:
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)

儘管POSIX標準中為條件變數定義了屬性,但在LinuxThreads中沒有實現,因此cond_attr值通常為NULL,且被忽略。

登出一個條件變數需要呼叫pthread_cond_destroy(),只有在沒有執行緒在該條件變數上等待的時候才能登出這個條件變數,否則返回EBUSY。因為Linux實現的條件變數沒有分配什麼資源,所以登出動作只包括檢查是否有等待執行緒。API定義如下:
int pthread_cond_destroy(pthread_cond_t *cond)

2. 等待和激發
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)

等待條件有兩種方式:無條件等待pthread_cond_wait()和計時等待pthread_cond_timedwait(),其中計時等待方式如果在給定時刻前條件沒有滿足,則返回ETIMEOUT,結束等待,其中abstime以與time()系統呼叫相同意義的絕對時間形式出現,0表示格林尼治時間1970年1月1日0時0分0秒。

無論哪種等待方式,都必須和一個互斥鎖配合,以防止多個執行緒同時請求pthread_cond_wait()(或pthread_cond_timedwait(),下同)的競爭條件(Race Condition)。mutex互斥鎖必須是普通鎖(PTHREAD_MUTEX_TIMED_NP)或者適應鎖(PTHREAD_MUTEX_ADAPTIVE_NP),且在呼叫pthread_cond_wait()前必須由本執行緒加鎖(pthread_mutex_lock()),而在更新條件等待佇列以前,mutex保持鎖定狀態,並在執行緒掛起進入等待前解鎖。在條件滿足從而離開pthread_cond_wait()之前,mutex將被重新加鎖,以與進入pthread_cond_wait()前的加鎖動作對應。

激發條件有兩種形式,pthread_cond_signal()啟用一個等待該條件的執行緒,存在多個等待執行緒時按入隊順序啟用其中一個;而pthread_cond_broadcast()則啟用所有等待執行緒。

3. 其他
pthread_cond_wait()和pthread_cond_timedwait()都被實現為取消點,因此,在該處等待的執行緒將立即重新執行,在重新鎖定mutex後離開pthread_cond_wait(),然後執行取消動作。也就是說如果pthread_cond_wait()被取消,mutex是保持鎖定狀態的,因而需要定義退出回撥函式來為其解鎖。

以下示例集中演示了互斥鎖和條件變數的結合使用,以及取消對於條件等待動作的影響。在例子中,有兩個執行緒被啟動,並等待同一個條件變數,如果不使用退出回撥函式(見範例中的註釋部分),則tid2將在pthread_mutex_lock()處永久等待。如果使用回撥函式,則tid2的條件等待及主執行緒的條件激發都能正常工作。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex;
pthread_cond_t  cond;

void * child1(void *arg)
{
        pthread_cleanup_push(pthread_mutex_unlock,&mutex);  /* comment 1 */
        while(1){
                printf("thread 1 get running \n");
        printf("thread 1 pthread_mutex_lock returns %d\n",
pthread_mutex_lock(&mutex));
        pthread_cond_wait(&cond,&mutex);
                    printf("thread 1 condition applied\n");
        pthread_mutex_unlock(&mutex);
                    sleep(5);
    }
        pthread_cleanup_pop(0);     /* comment 2 */
}

void *child2(void *arg)
{
        while(1){
                sleep(3);               /* comment 3 */
                printf("thread 2 get running.\n");
        printf("thread 2 pthread_mutex_lock returns %d\n",
pthread_mutex_lock(&mutex));
        pthread_cond_wait(&cond,&mutex);
        printf("thread 2 condition applied\n");
        pthread_mutex_unlock(&mutex);
        sleep(1);
        }
}

int main(void)
{
        int tid1,tid2;

        printf("hello, condition variable test\n");
        pthread_mutex_init(&mutex,NULL);
        pthread_cond_init(&cond,NULL);
        pthread_create(&tid1,NULL,child1,NULL);
        pthread_create(&tid2,NULL,child2,NULL);
        do{
        sleep(2);                   /* comment 4 */
                pthread_cancel(tid1);       /* comment 5 */
                sleep(2);                   /* comment 6 */
        pthread_cond_signal(&cond);
    }while(1); 
        sleep(100);
        pthread_exit(0);
}





如果不做註釋5的pthread_cancel()動作,即使沒有那些sleep()延時操作,child1和child2都能正常工作。註釋3和註釋4的延遲使得child1有時間完成取消動作,從而使child2能在child1退出之後進入請求鎖操作。如果沒有註釋1和註釋2的回撥函式定義,系統將掛起在child2請求鎖的地方;而如果同時也不做註釋3和註釋4的延時,child2能在child1完成取消動作以前得到控制,從而順利執行申請鎖的操作,但卻可能掛起在pthread_cond_wait()中,因為其中也有申請mutex的操作。child1函式給出的是標準的條件變數的使用方式:回撥函式保護,等待條件前鎖定,pthread_cond_wait()返回後解鎖。

條件變數機制不是非同步訊號安全的,也就是說,在訊號處理函式中呼叫pthread_cond_signal()或者pthread_cond_broadcast()很可能引起死鎖。

三.訊號燈
訊號燈與互斥鎖和條件變數的主要不同在於"燈"的概念,燈亮則意味著資源可用,燈滅則意味著不可用。如果說後兩中同步方式側重於"等待"操作,即資源不可用的話,訊號燈機制則側重於點燈,即告知資源可用;沒有等待執行緒的解鎖或激發條件都是沒有意義的,而沒有等待燈亮的執行緒的點燈操作則有效,且能保持燈亮狀態。當然,這樣的操作原語也意味著更多的開銷。

訊號燈的應用除了燈亮/燈滅這種二元燈以外,也可以採用大於1的燈數,以表示資源數大於1,這時可以稱之為多元燈。

1. 建立和登出
POSIX訊號燈標準定義了有名訊號燈和無名訊號燈兩種,但LinuxThreads的實現僅有無名燈,同時有名燈除了總是可用於多程序之間以外,在使用上與無名燈並沒有很大的區別,因此下面僅就無名燈進行討論。

int sem_init(sem_t *sem, int pshared, unsigned int value)
這是建立訊號燈的API,其中value為訊號燈的初值,pshared表示是否為多程序共享而不僅僅是用於一個程序。LinuxThreads沒有實現多程序共享訊號燈,因此所有非0值的pshared輸入都將使sem_init()返回-1,且置errno為ENOSYS。初始化好的訊號燈由sem變量表徵,用於以下點燈、滅燈操作。

int sem_destroy(sem_t * sem)
被登出的訊號燈sem要求已沒有執行緒在等待該訊號燈,否則返回-1,且置errno為EBUSY。除此之外,LinuxThreads的訊號燈登出函式不做其他動作。

2. 點燈和滅燈
int sem_post(sem_t * sem)
點燈操作將訊號燈值原子地加1,表示增加一個可訪問的資源。

int sem_wait(sem_t * sem)
int sem_trywait(sem_t * sem)
sem_wait()為等待燈亮操作,等待燈亮(訊號燈值大於0),然後將訊號燈原子地減1,並返回。sem_trywait()為sem_wait()的非阻塞版,如果訊號燈計數大於0,則原子地減1並返回0,否則立即返回-1,errno置為EAGAIN。

3. 獲取燈值
int sem_getvalue(sem_t * sem, int * sval)
讀取sem中的燈計數,存於*sval中,並返回0。

4. 其他
sem_wait()被實現為取消點,而且在支援原子"比較且交換"指令的體系結構上,sem_post()是唯一能用於非同步訊號處理函式的POSIX非同步訊號安全的API。

四.非同步訊號
由於LinuxThreads是在核外使用核內輕量級程序實現的執行緒,所以基於核心的非同步訊號操作對於執行緒也是有效的。但同時,由於非同步訊號總是實際發往某個程序,所以無法實現POSIX標準所要求的"訊號到達某個程序,然後再由該程序將訊號分發到所有沒有阻塞該訊號的執行緒中"原語,而是隻能影響到其中一個執行緒。

POSIX非同步訊號同時也是一個標準C庫提供的功能,主要包括訊號集管理(sigemptyset()、sigfillset()、sigaddset()、sigdelset()、sigismember()等)、訊號處理函式安裝(sigaction())、訊號阻塞控制(sigprocmask())、被阻塞訊號查詢(sigpending())、訊號等待(sigsuspend())等,它們與傳送訊號的kill()等函式配合就能實現程序間非同步訊號功能。LinuxThreads圍繞執行緒封裝了sigaction()和raise(),本節集中討論LinuxThreads中擴充套件的非同步訊號函式,包括pthread_sigmask()、pthread_kill()和sigwait()三個函式。毫無疑問,所有POSIX非同步訊號函式對於執行緒都是可用的。

int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask)
設定執行緒的訊號遮蔽碼,語義與sigprocmask()相同,但對不允許遮蔽的Cancel訊號和不允許響應的Restart訊號進行了保護。被遮蔽的訊號儲存在訊號佇列中,可由sigpending()函式取出。

int pthread_kill(pthread_t thread, int signo)
向thread號執行緒傳送signo訊號。實現中在通過thread執行緒號定位到對應程序號以後使用kill()系統呼叫完成傳送。

int sigwait(const sigset_t *set, int *sig)
掛起執行緒,等待set中指定的訊號之一到達,並將到達的訊號存入*sig中。POSIX標準建議在呼叫sigwait()等待訊號以前,程序中所有執行緒都應遮蔽該訊號,以保證僅有sigwait()的呼叫者獲得該訊號,因此,對於需要等待同步的非同步訊號,總是應該在建立任何執行緒以前呼叫pthread_sigmask()遮蔽該訊號的處理。而且,呼叫sigwait()期間,原來附接在該訊號上的訊號處理函式不會被呼叫。

如果在等待期間接收到Cancel訊號,則立即退出等待,也就是說sigwait()被實現為取消點。

五.其他同步方式
除了上述討論的同步方式以外,其他很多程序間通訊手段對於LinuxThreads也是可用的,比如基於檔案系統的IPC(管道、Unix域Socket等)、訊息佇列(Sys.V或者Posix的)、System V的訊號燈等。只有一點需要注意,LinuxThreads在核內是作為共享儲存區、共享檔案系統屬性、共享訊號處理、共享檔案描述符的獨立程序看待的。



Posix執行緒程式設計指南(4)   


  
內容:

1. 執行緒終止方式
2. 執行緒終止時的清理
3. 執行緒終止的同步及其返回值
4. 關於pthread_exit()和return
參考資料
關於作者


相關內容:

(1) 執行緒建立與取消 
(2) 執行緒私有資料 
(3) 執行緒同步 




執行緒終止
楊沙洲(
[email protected]
)
2001 年 11 月

這是一個關於Posix執行緒程式設計的專欄。作者在闡明概念的基礎上,將向您詳細講述Posix執行緒庫API。本文是第四篇將向您講述執行緒中止。
1.執行緒終止方式
一般來說,Posix的執行緒終止有兩種情況:正常終止和非正常終止。執行緒主動呼叫pthread_exit()或者從執行緒函式中return都將使執行緒正常退出,這是可預見的退出方式;非正常終止是執行緒在其他執行緒的干預下,或者由於自身執行出錯(比如訪問非法地址)而退出,這種退出方式是不可預見的。

2.執行緒終止時的清理
不論是可預見的執行緒終止還是異常終止,都會存在資源釋放的問題,在不考慮因執行出錯而退出的前提下,如何保證執行緒終止時能順利的釋放掉自己所佔用的資源,特別是鎖資源,就是一個必須考慮解決的問題。

最經常出現的情形是資源獨佔鎖的使用:執行緒為了訪問臨界資源而為其加上鎖,但在訪問過程中被外界取消,如果執行緒處於響應取消狀態,且採用非同步方式響應,或者在開啟獨佔鎖以前的執行路徑上存在取消點,則該臨界資源將永遠處於鎖定狀態得不到釋放。外界取消操作是不可預見的,因此的確需要一個機制來簡化用於資源釋放的程式設計。

在POSIX執行緒API中提供了一個pthread_cleanup_push()/pthread_cleanup_pop()函式對用於自動釋放資源--從pthread_cleanup_push()的呼叫點到pthread_cleanup_pop()之間的程式段中的終止動作(包括呼叫pthread_exit()和取消點終止)都將執行pthread_cleanup_push()所指定的清理函式。API定義如下:

void pthread_cleanup_push(void (*routine) (void  *),  void *arg)
void pthread_cleanup_pop(int execute)






pthread_cleanup_push()/pthread_cleanup_pop()採用先入後出的棧結構管理,void routine(void *arg)函式在呼叫pthread_cleanup_push()時壓入清理函式棧,多次對pthread_cleanup_push()的呼叫將在清理函式棧中形成一個函式鏈,在執行該函式鏈時按照壓棧的相反順序彈出。execute引數表示執行到pthread_cleanup_pop()時是否在彈出清理函式的同時執行該函式,為0表示不執行,非0為執行;這個引數並不影響異常終止時清理函式的執行。

pthread_cleanup_push()/pthread_cleanup_pop()是以巨集方式實現的,這是pthread.h中的巨集定義:

#define pthread_cleanup_push(routine,arg)                                     \
  { struct _pthread_cleanup_buffer _buffer;                                   \
    _pthread_cleanup_push (&_buffer, (routine), (arg));
#define pthread_cleanup_pop(execute)                                          \
    _pthread_cleanup_pop (&_buffer, (execute)); }






可見,pthread_cleanup_push()帶有一個"{",而pthread_cleanup_pop()帶有一個"}",因此這兩個函式必須成對出現,且必須位於程式的同一級別的程式碼段中才能通過編譯。在下面的例子裡,當執行緒在"do some work"中終止時,將主動呼叫pthread_mutex_unlock(mut),以完成解鎖動作。

pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
pthread_mutex_lock(&mut);
/* do some work */
pthread_mutex_unlock(&mut);
pthread_cleanup_pop(0);






必須要注意的是,如果執行緒處於PTHREAD_CANCEL_ASYNCHRONOUS狀態,上述程式碼段就有可能出錯,因為CANCEL事件有可能在pthread_cleanup_push()和pthread_mutex_lock()之間發生,或者在pthread_mutex_unlock()和pthread_cleanup_pop()之間發生,從而導致清理函式unlock一個並沒有加鎖的mutex變數,造成錯誤。因此,在使用清理函式的時候,都應該暫時設定成PTHREAD_CANCEL_DEFERRED模式。為此,POSIX的Linux實現中還提供了一對不保證可移植的pthread_cleanup_push_defer_np()/pthread_cleanup_pop_defer_np()擴充套件函式,功能與以下程式碼段相當:

{ int oldtype;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
pthread_cleanup_push(routine, arg);
...
pthread_cleanup_pop(execute);
pthread_setcanceltype(oldtype, NULL);
}





3.執行緒終止的同步及其返回值
一般情況下,程序中各個執行緒的執行都是相互獨立的,執行緒的終止並不會通知,也不會影響其他執行緒,終止的執行緒所佔用的資源也並不會隨著執行緒的終止而得到釋放。正如程序之間可以用wait()系統呼叫來同步終止並釋放資源一樣,執行緒之間也有類似機制,那就是pthread_join()函式。

void pthread_exit(void *retval)
int pthread_join(pthread_t th, void **thread_return)
int pthread_detach(pthread_t th)






pthread_join()的呼叫者將掛起並等待th執行緒終止,retval是pthread_exit()呼叫者執行緒(執行緒ID為th)的返回值,如果thread_return不為NULL,則*thread_return=retval。需要注意的是一個執行緒僅允許唯一的一個執行緒使用pthread_join()等待它的終止,並且被等待的執行緒應該處於可join狀態,即非DETACHED狀態。

如果程序中的某個執行緒執行了pthread_detach(th),則th執行緒將處於DETACHED狀態,這使得th執行緒在結束執行時自行釋放所佔用的記憶體資源,同時也無法由pthread_join()同步,pthread_detach()執行之後,對th請求pthread_join()將返回錯誤。

一個可join的執行緒所佔用的記憶體僅當有執行緒對其執行了pthread_join()後才會釋放,因此為了避免記憶體洩漏,所有執行緒的終止,要麼已設為DETACHED,要麼就需要使用pthread_join()來回收。

4.關於pthread_exit()和return
理論上說,pthread_exit()和執行緒宿體函式退出的功能是相同的,函式結束時會在內部自動呼叫pthread_exit()來清理執行緒相關的資源。但實際上二者由於編譯器的處理有很大的不同。

在程序主函式(main())中呼叫pthread_exit(),只會使主函式所在的執行緒(可以說是程序的主執行緒)退出;而如果是return,編譯器將使其呼叫程序退出的程式碼(如_exit()),從而導致程序及其所有執行緒結束執行。

其次,線上程宿主函式中主動呼叫return,如果return語句包含在pthread_cleanup_push()/pthread_cleanup_pop()對中,則不會引起清理函式的執行,反而會導致segment fault。

相關推薦

POSIX執行操作有點將就記錄一下

Posix執行緒程式設計指南(3)       內容: 一. 互斥鎖 二. 條件變數 三. 訊號燈 四. 非同步訊號 五. 其他同步方式 關於作者 相關內容: (1) 執行緒建立與取消  (2) 執行緒私有資料  執行緒同步 楊沙洲([email protected]) 2

程序/執行同步的方式和機制程序間通訊【

(轉自:https://www.cnblogs.com/virusolf/p/5331946.html) 一、程序/執行緒間同步機制。 臨界區、互斥區、事件、訊號量四種方式臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)的區別

Rxjava - 操作符執行操作的簡單使用

目錄 建立操作符 10種常用的操作符定義 下面做幾個操作符的demo演示 create from repeat defer interval Scheduler 什麼是Sc

c#winform跨執行操作控制元件的一種方法InvokeRequired

  在winform裡面如果有建立新執行緒的話,線上程裡面直接操作控制元件或修改控制元件的屬性是不允許的,雖然有辦法讓程式執行時忽略跨執行緒可能產生的問題,從而解決;但是從科學的角度看,該辦法並不可取,所以我就用了InvokeRequired的辦法解決跨執行緒操作問題。  

c#多執行操作測試(阻塞執行結束任務)

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Te

C# 多執行操作介面時使用Invoke與BeginInvoke的區別

Invoke方法的引數很簡單,一個委託,一個引數表(可選),而Invoke方法的主要功能就是幫助你在 UI執行緒(即建立控制元件的執行緒)上呼叫委託所指定的方法。Invoke方法首先檢查發出呼叫的執行緒(即當前執行緒)是不是UI執行緒,如果是,直接執行委託指向 的方法

[Windows10]記一次修復註冊表相關血案:該文件沒有與之關聯的應用來執行操作。請安裝應用若已經安裝應用請在“默認應用設置”頁面中創建關聯。

src 相關 overflow 還在 一次 註冊表 forum sin 嘗試 今天閑得蛋疼清理了一下右鍵菜單,於是在之後某時刻使用Everything的“雙擊路徑列打開目錄”功能時發現異常: [Window Title] Everything

Java執行操作

轉載請標明出處:http://blog.csdn.net/wu_wxc/article/details/51764557 本文出自【吳孝城的CSDN部落格】 Java中執行緒的實現有兩種方法 繼承Thread類 實現Runnable介面 執行緒的狀態 新

Linux — POSIX 執行基礎

執行緒對於Linux後臺程式設計師來說並不陌生,執行緒帶給我們併發能力的提升,也提高了軟體開發和問題定位的難度,本文 嘗試結合GlibC 程式碼, 對POSIX的執行緒做一個簡單說明,重點介紹執行緒的建立,釋放和連線上需要注意的問題。 多程序和多執行緒的都只有一個目的,並行處理,提高CP

tensorflow--開啟執行操作

執行緒非同步 在訓練過程中,可以通過非同步讀取資料,加快程式執行速度 1. 操作過程 1.1. 定義要做的事情 例如讀取檔案,此處示例就變數自加好了: var = tf.Variable(0.0) data = tf.assign_add(var,tf.constant(

beginthreadex()函式在建立多執行傳入回撥函式時好像只能傳入全域性函式或類的靜態成員函式請問能不能傳入類的成員函式呢(非靜態)?

C++類成員函式直接作為執行緒回撥函式2009年06月01日 星期一 17:01我以前寫執行緒時要麼老老實實照著宣告寫,要麼使用C++類的靜態成員函式來作為回撥函式,經常會因為執行緒程式碼而破壞封裝.之前雖然知道類成員函式的展開形式,但從沒想過利用過它,昨天看深入ATL時無意中學

C# 解決子執行不能操作主執行UI(介面)問題涉及到多執行的概念。

1、在預設情況下,C#不准許在一個執行緒中直接訪問或操作另一執行緒中建立的控制元件,這是因為訪問windows窗體控制元件本質上是不安全的。 2、執行緒之間是可以同時執行的,那麼如果有兩個或多個執行緒同時操作某一控制元件的某狀態,嘗試將一個控制元件變為自己需要的狀態時, 執行緒的死鎖就可能發生。

2017.10.20 C#跨執行操作控制元件的執行安全方法

C#跨執行緒操作控制元件的執行緒安全方法 在C#中,經常用到這樣一個場景,Windows Form程式啟動一個工作者執行緒執行一部分工作,這樣做是為了避免速度慢的工作如果直接呼叫會使得主Form停止響應一段時間。 既然啟動了執行緒,就避免不了執行緒之間資料傳遞的事情,相信你有很多種辦法

Qt 執行操作

方法一:movetothread 將物件移入子執行緒,通過訊號槽來分配任務以及資訊傳遞,這也是Qt推薦的做法。 auto thread = new QThread(); auto sbsImporter = new SoloSbsImporter(); sbsImport

如何實現自己的執行池(不看後悔一看必懂)

首先,在服務啟動的時候,我們可以啟動好幾個執行緒,並用一個容器(如執行緒池)來管理這些執行緒。當請求到來時,可以從池中取一個執行緒出來,執行任務(通常是對請求的響應),當任務結束後,再將這個執行緒放入池中備用;如果請求到來而池中沒有空閒的執行緒,該請求需要排隊等候。最後,當服務關閉時銷燬該池即可

java中常見的執行池(不看後悔一看必懂)

Executor介面表示執行緒池,它的execute(Runnable task)方法用來執行Runnable型別的任務,ExecutorService是Executor的子介面,聲明瞭管理執行緒池的一些方法 Java.util.concurrent.Executors類包含了一些靜態

python多執行————3、多執行間通訊:共享變數queue

1、共享變數 #通過共享變數 import time import threading url_list = [] def get_detail_html(): global url_list while True: if len(url_list):

執行操作案例---生產者與消費者

class Producer implements Runnable{ //通過Runnable實現多執行緒 private Info info = null; //儲存Info引用 public Producer(Info info) { this.info = info; }

git 日常命令(整理有點都是筆記)

git stash pop #取回暫存的內容,自動檢測合併 git stash list #檢視"暫存區"的所有記錄 git stash clear #清空"暫存區" git stash pop #取回暫存區第一個記錄 git stash apply 0 #取回"暫存區"指定的記錄 編號

C# 多執行學習系列四之取消、超時子執行操作

1、簡介 雖然ThreadPool、Thread能開啟子執行緒將一些任務交給子執行緒去承擔,但是很多時候,因為某種原因,比如子執行緒發生異常、或者子執行緒的業務邏輯不符合我們的預期,那麼這個時候我們必須關閉它,而不是讓它繼續執行,消耗資源.讓CPU不在把時間和資源花在沒有意義的程式碼上.