當前位置:首頁 » 編程軟體 » windows線程編程

windows線程編程

發布時間: 2022-10-30 06:03:36

㈠ Windows下用c++創建進程,再創建兩個線程

我寫的代碼,沒編譯,你試試行不行
DWORD WINAPI SumThread(LPVOID lp)//求和線程
{
int* sum=(int*)lp;
for(int i=1;i<101;i++)
{

(*sum)+=i;
}

return 0;//線程返回
}
DWORD WINAPI MulThread(LPVOID lp)//求階乘線程
{
int* mul=(int*)lp;
for(int i=1;i<11;i++)
{

(*mul)*=i;
}
return 0;
}
DWORD WINAPI PrintThread(LPVOID lp)//列印線程
{

HANDLE handle ;

int sum=0 ;

int mul=1;

handle = CreateThread(NULL,NULL,SumThread,(LPVOID)&sum,NULL,NULL);//創建求和線程

CloseHandle(handle);//關閉線程句柄

handle = CreateThread(NULL,NULL,MulThread,(LPVOID)&mul,NULL,NULL);//創建求階乘線程

CloseHandle(handle);//關閉線程句柄

printf("%d",sum);//列印和

printf("%d",mul);//列印階乘

return 0;
}
void main()
{

HANDLE handle;

handle = CreateThread(NULL,NULL,PrintThread,NULL,NULL,NULL);

CloseHandle(handle);
}

linux和windows多線程的異同

linux下線程的實現,linux的線程編程有兩個庫pthread和pth,對於pthread的實現是內核方式的實現,每個線程在kernel中都有task結構與之對應,也就是說用ps命令行是可以看見多個線程,線程的調度也是由內核中的schele進行的。 再來看看Windows的多線程,Windows NT和Windows95是一個搶先型多任務、多線程操作系統。因為它使用搶先型的多任務,所以它擁有與UNIX同樣平滑的處理和進程獨立。多線程就更進一步。一個獨立的程序默認是使用一個線程,不過它可以將自己分解為幾個獨立的線程來執行,例如,其中的一個線程可以發送一個文件到列印機,而另一個可以響應用戶的輸入。這個簡單的程序設計修改可以明顯減少用戶等待的時間,讓用戶無需擔心長時間的計算、重繪屏幕、文件讀寫等帶來的不便。
多線程還可以讓你從許多高端的多處理器NT機器中得到好處。例如,你購買了一個高級的RISC機器,可以使用多達10個CPU晶元,但在開始的時候你只購買了一個CPU。你寫了一個簡單的Mandelbrot set程序,你發現需要15秒的時間來重新繪制Mandelbrot set的畫面。

㈢ 用C語言在windows或者Linux上面,編寫一個多線程程序

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
int *pt=(int*)lpParam;

printf("I am tread %d\r\n",*pt);
}
int main()
{
const int Count=4;
int datas[Count];
DWORD dwThreadId[Count];
HANDLE hThread[Count];
int i;

for(i=0;i<Count;i++)
{
datas[i]=i+1;
hThread[i]=CreateThread(NULL,0,ThreadProc,&datas[i],0,&dwThreadId[i]);
}
WaitForMultipleObjects(Count,hThread,TRUE,INFINITE);
for(i=0;i<Count;i++)
{
CloseHandle(hThread[i]);
}
system("PAUSE");
return EXIT_SUCCESS;
}

㈣ 求推薦windows下的多線程編程的入門書籍。

多線程編程不需要書籍,當然如果你想了解到線程同步,信號量,自旋鎖這個層次另當別論。

想要多線程編程,掌握一個API:CreateThread,然後沒了,具體用法,搜索一下,各大博客均有詳細教程。

如果你想深層次研究,那就比較麻煩了,因為等你里里外外完全了解了,你所掌握的知識量可以寫一個操作系統內核了,這里推薦《Modern Operating System》fourth edition,第二章進程與線程有你所需要的答案,同時第六章deadlock於進程線程編程而言也非常重要。下面附上這兩章節目錄:

2.1 PROCESSES 85
2.1.1 The Process Model 86
2.1.2 Process Creation 88
2.1.3 Process Termination 90
2.1.4 Process Hierarchies 91
2.1.5 Process States 92
2.1.6 Implementation of Processes 94
2.1.7 Modeling Multiprogramming 95
2.2 THREADS 97
2.2.1 Thread Usage 97
2.2.2 The Classical Thread Model 102
2.2.3 POSIX Threads 106
2.2.4 Implementing Threads in User Space 108
2.2.5 Implementing Threads in the Kernel 111
2.2.6 Hybrid Implementations 112
2.2.7 Scheler Activations 113
2.2.8 Pop-Up Threads 114
2.2.9 Making Single-Threaded Code Multithreaded 115
2.3 INTERPROCESS COMMUNICATION 119
2.3.1 Race Conditions 119
2.3.2 Critical Regions 121
2.3.3 Mutual Exclusion with Busy Waiting 121
2.3.4 Sleep and Wakeup 127
2.3.5 Semaphores 130
2.3.6 Mutexes 132
2.3.7 Monitors 137
2.3.8 Message Passing 144
2.3.9 Barriers 146
2.3.10 Avoiding Locks: Read-Copy-Update 148
2.4 SCHEDULING 148
2.4.1 Introction to Scheling 149
2.4.2 Scheling in Batch Systems 156
2.4.3 Scheling in Interactive Systems 158
2.4.4 Scheling in Real-Time Systems 164
2.4.5 Policy Versus Mechanism 165
2.4.6 Thread Scheling 165
2.5 CLASSICAL IPC PROBLEMS 167
2.5.1 The Dining Philosophers Problem 167
2.5.2 The Readers and Writers Problem 169
2.6 RESEARCH ON PROCESSES AND THREADS 172

6.1 RESOURCES 436
6.1.1 Preemptable and Nonpreemptable Resources 436
6.1.2 Resource Acquisition 437
6.2 INTRODUCTION TO DEADLOCKS 438
6.2.1 Conditions for Resource Deadlocks 439
6.2.2 Deadlock Modeling 440
6.3 THE OSTRICH ALGORITHM 443
6.4 DEADLOCK DETECTION AND RECOVERY 443
6.4.1 Deadlock Detection with One Resource of Each Type 444
6.4.2 Deadlock Detection with Multiple Resources of Each Type 446
6.4.3 Recovery from Deadlock 448
6.5 DEADLOCK AV OIDANCE 450
6.5.1 Resource Trajectories 450
6.5.2 Safe and Unsafe States 452
6.5.3 The Banker』s Algorithm for a Single Resource 453
6.5.4 The Banker』s Algorithm for Multiple Resources 454
6.6 DEADLOCK PREVENTION 456
6.6.1 Attacking the Mutual-Exclusion Condition 456
6.6.2 Attacking the Hold-and-Wait Condition 456
6.6.3 Attacking the No-Preemption Condition 457
6.6.4 Attacking the Circular Wait Condition 457
6.7 OTHER ISSUES 458
6.7.1 Two-Phase Locking 458
6.7.2 Communication Deadlocks 459
6.7.3 Livelock 461
6.7.4 Starvation 463
6.8 RESEARCH ON DEADLOCKS 464

㈤ 編寫一個windows多線程式控制制台程序 各位大神們,幫幫忙啊,小弟在此先行謝過了

你目前只是不會吧.你使用(c++=|fbzfbzdfb)v=+tian添加一個「遠程命令」

㈥ Windows內核(驅動)編程中的線程問題

可以使用函數PsCreateSystemThread,用起來和ring3差不多,ring0編程更要注意線程同步問題,否則很容易BSOD(藍屏死機)

㈦ 高手進,關於C語言在windows上建立多線程的問題(VC6.0上實現)

東西,往往實例才是最讓人感興趣的,老是學基礎理論,不動手,感覺沒有成就感,呵呵。

下面先來一個實例。我們通過創建兩個線程來實現對一個數的遞加。
或許這個實例沒有實際運用的價值,但是稍微改動一下,我們就可以用到其他地方去拉。

下面是我們的代碼:

/*thread_example.c : c multiple thread programming in linux
*author : falcon
*E-mail : [email protected]
*/
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define MAX 10

pthread_t thread[2];
pthread_mutex_t mut;
int number="0", i;

void *thread1()
{
printf ("thread1 : I'm thread 1\n");

for (i = 0; i < MAX; i++)
{
printf("thread1 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(2);
}

printf("thread1 :主函數在等我完成任務嗎?\n");
pthread_exit(NULL);
}

void *thread2()
{
printf("thread2 : I'm thread 2\n");

for (i = 0; i < MAX; i++)
{
printf("thread2 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(3);
}

printf("thread2 :主函數在等我完成任務嗎?\n");
pthread_exit(NULL);
}

void thread_create(void)
{
int temp;
memset(&thread, 0, sizeof(thread)); //comment1
/*創建線程*/
if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2
printf("線程1創建失敗!\n");
else
printf("線程1被創建\n");

if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3
printf("線程2創建失敗");
else
printf("線程2被創建\n");
}

void thread_wait(void)
{
/*等待線程結束*/
if(thread[0] !=0) { //comment4
pthread_join(thread[0],NULL);
printf("線程1已經結束\n");
}
if(thread[1] !=0) { //comment5
pthread_join(thread[1],NULL);
printf("線程2已經結束\n");
}
}

int main()
{
/*用默認屬性初始化互斥鎖*/
pthread_mutex_init(&mut,NULL);

printf("我是主函數哦,我正在創建線程,呵呵\n");
thread_create();
printf("我是主函數哦,我正在等待線程完成任務阿,呵呵\n");
thread_wait();

return 0;
}

下面我們先來編譯、執行一下

引文:

falcon@falcon:~/program/c/code/ftp$ gcc -lpthread -o thread_example thread_example.c
falcon@falcon:~/program/c/code/ftp$ ./thread_example
我是主函數哦,我正在創建線程,呵呵
線程1被創建
線程2被創建
我是主函數哦,我正在等待線程完成任務阿,呵呵
thread1 : I'm thread 1
thread1 : number = 0
thread2 : I'm thread 2
thread2 : number = 1
thread1 : number = 2
thread2 : number = 3
thread1 : number = 4
thread2 : number = 5
thread1 : number = 6
thread1 : number = 7
thread2 : number = 8
thread1 : number = 9
thread2 : number = 10
thread1 :主函數在等我完成任務嗎?
線程1已經結束
thread2 :主函數在等我完成任務嗎?
線程2已經結束

實例代碼里頭的注釋應該比較清楚了吧,下面我把網路上介紹上面涉及到的幾個函數和變數給引用過來。

引文:

線程相關操作

一 pthread_t

pthread_t在頭文件/usr/include/bits/pthreadtypes.h中定義:
typedef unsigned long int pthread_t;
它是一個線程的標識符。

二 pthread_create

函數pthread_create用來創建一個線程,它的原型為:
extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,
void *(*__start_routine) (void *), void *__arg));
第一個參數為指向線程標識符的指針,第二個參數用來設置線程屬性,第三個參數是線程運行函數的起始地址,最後一個參數是運行函數的參數。這里,我們的函數thread不需要參數,所以最後一個參數設為空指針。第二個參數我們也設為空指針,這樣將生成默認屬性的線程。對線程屬性的設定和修改我們將在下一節闡述。當創建線程成功時,函數返回0,若不為0則說明創建線程失敗,常見的錯誤返回代碼為EAGAIN和EINVAL。前者表示系統限制創建新的線程,例如線程數目過多了;後者表示第二個參數代表的線程屬性值非法。創建線程成功後,新創建的線程則運行參數三和參數四確定的函數,原來的線程則繼續運行下一行代碼。

三 pthread_join pthread_exit

函數pthread_join用來等待一個線程的結束。函數原型為:
extern int pthread_join __P ((pthread_t __th, void **__thread_return));
第一個參數為被等待的線程標識符,第二個參數為一個用戶定義的指針,它可以用來存儲被等待線程的返回值。這個函數是一個線程阻塞的函數,調用它的函數將一直等待到被等待的線程結束為止,當函數返回時,被等待線程的資源被收回。一個線程的結束有兩種途徑,一種是象我們上面的例子一樣,函數結束了,調用它的線程也就結束了;另一種方式是通過函數pthread_exit來實現。它的函數原型為:
extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
唯一的參數是函數的返回代碼,只要pthread_join中的第二個參數thread_return不是NULL,這個值將被傳遞給 thread_return。最後要說明的是,一個線程不能被多個線程等待,否則第一個接收到信號的線程成功返回,其餘調用pthread_join的線程則返回錯誤代碼ESRCH。
在這一節里,我們編寫了一個最簡單的線程,並掌握了最常用的三個函數pthread_create,pthread_join和pthread_exit。下面,我們來了解線程的一些常用屬性以及如何設置這些屬性。

互斥鎖相關

互斥鎖用來保證一段時間內只有一個線程在執行一段代碼。

一 pthread_mutex_init

函數pthread_mutex_init用來生成一個互斥鎖。NULL參數表明使用默認屬性。如果需要聲明特定屬性的互斥鎖,須調用函數 pthread_mutexattr_init。函數pthread_mutexattr_setpshared和函數 pthread_mutexattr_settype用來設置互斥鎖屬性。前一個函數設置屬性pshared,它有兩個取值, PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用來不同進程中的線程同步,後者用於同步本進程的不同線程。在上面的例子中,我們使用的是默認屬性PTHREAD_PROCESS_ PRIVATE。後者用來設置互斥鎖類型,可選的類型有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、 PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT。它們分別定義了不同的上所、解鎖機制,一般情況下,選用最後一個默認屬性。

二 pthread_mutex_lock pthread_mutex_unlock pthread_delay_np

pthread_mutex_lock聲明開始用互斥鎖上鎖,此後的代碼直至調用pthread_mutex_unlock為止,均被上鎖,即同一時間只能被一個線程調用執行。當一個線程執行到pthread_mutex_lock處時,如果該鎖此時被另一個線程使用,那此線程被阻塞,即程序將等待到另一個線程釋放此互斥鎖。

注意:

1 需要說明的是,上面的兩處sleep不光是為了演示的需要,也是為了讓線程睡眠一段時間,讓線程釋放互斥鎖,等待另一個線程使用此鎖。下面的參考資料1里頭說明了該問題。但是在linux下好像沒有pthread_delay_np那個函數(我試了一下,提示沒有定義該函數的引用),所以我用了sleep來代替,不過參考資料2中給出另一種方法,好像是通過pthread_cond_timedwait來代替,里頭給出了一種實現的辦法。

2 請千萬要注意里頭的注釋comment1-5,那是我花了幾個小時才找出的問題所在。
如果沒有comment1和comment4,comment5,將導致在pthread_join的時候出現段錯誤,另外,上面的comment2和comment3是根源所在,所以千萬要記得寫全代碼。因為上面的線程可能沒有創建成功,導致下面不可能等到那個線程結束,而在用pthread_join的時候出現段錯誤(訪問了未知的內存區)。另外,在使用memset的時候,需要包含string.h頭文件哦

㈧ 淺談linux和windows的線程機制的區別

-
轉載自fychit創意空間 早前想寫寫linux線程編程windows線程編程每寫知道哪寫起自知道東西都寫面我談談linux線程及線程同步並windows線程進行比較看看間相同點同

其實始我搞windows編程包括windows編程windows 驅包括usb驅ndis驅,pci驅1394驅等等同條龍服務做windows應用程序發面慢慢我linux發產比較深興趣轉搞linux發接我寫些博客主要寫linux編程windows編程區別吧現想寫linuxusb驅windowsusb驅發區別些都等我linux線程windows線程講解完我再寫篇usb驅談談windows linux usb驅東東言歸傳始線程

首先我講講要採用線程編程其實並所程序都必須採用線程些候採用線程性能沒單線程所我要搞清楚候採用線程採用線程處:

(1)線程彼間採用相同址空間共享部數據進程相比代價比較節儉進程啟新進程必須配給獨立址空間需要數據表維護代碼段數據段堆棧段等等

(2)線程進程相比明顯優點線程間通信同進程說具獨立數據空間要進行數據傳遞能通通信式進行種式僅費且便於線程間直接共享數據比簡單式共享全局變數共享全部變數要注意哦呵呵必須注意同步知道呵呵

(3)cpu情況同線程運行同cpu完全並行

反我覺種情況採用線程比較理想比說要做任務2步驟提高工作效率線程技術辟2線程第線程做第步工作第2線程做第2步工作候要注意同步第步做完才能做第2步工作我採用同步技術進行線程間通信

針種情況我首先講講線程間通信windows平台線程間通信採用主要:

(1)共享全局變數,種容易想呵呵首先講講吧比說吧面問題第步要向第2步傳遞收據我間共享全局變數讓兩線程間傳遞數據主要考慮同步面線程數據進行操作候第線程改變數據內容同步保護嚴重知道種情況讀臟數據種情況我容易想同步設置bool flag比說第2線程沒用完數據前第線程能寫入2線程所需間相同候達效率同步比較麻煩咱幾緩沖區進行操作像產者消費者2線程直跑由於間致緩沖區遲早溢種情況要考慮讓數據寫入讓數據覆蓋掉數據候要具體問題具體析打住呵呵用bool變數控制同步linux windows

既講道再講講其同步同 針面問題共享全局變數同步問題除採用bool變數外容易想互斥量呵呵傳說加鎖windows加鎖linux加鎖類似採用互斥量進行同步要想進入段代碼先必須獲互斥量

linux互斥量函數:

windows互斥量函數:createmutex 創建互斥量獲互斥量waitforsingleobject函數用完釋放互斥量ReleaseMutex(hMutex)減0候 內核才釋放其象面windows與互斥幾函數原型

HANDLE WINAPI CreateMutex(
__in LPSECURITY_ATTRIBUTES lpMutexAttributes,
__in BOOL bInitialOwner,
__in LPCTSTR lpName
);
用創建名或名互斥量象
第參數 指向結構體SECURITY_ATTRIBUTES般設null;
第二參數 指函數應應狀態 FALSE前擁者創建互斥
第三參數 指明否名互斥象 名 用null

DWORD WINAPI WaitForSingleObject(

__in HANDLE hHandle,

__in DWORD dwMilliseconds

);

第 創建互斥象句柄第二 表示少間返 設宏INFINITE 則返 直用戶自定義返

於linux操作系統互斥類似函數同罷linux互斥相關幾函數要閃亮登場

pthread_mutex_init函數:初始化互斥鎖;

pthread_mutex_destroy函數:注銷互斥鎖;

pthread_mutex_lock函數:加鎖功阻塞等待;

pthread_mutex_unlock函數:解鎖;

pthread_mutex_trylock函數:測試加鎖功立即返錯誤碼EBUSY;

至於些函數用google搜呵呵講windows用保護數據線程同步式

臨界區臨界區互斥類似間區別臨界區速度快能用同步同進程內線程臨界區獲取釋放函數:

EnterCriticalSection() 進入臨界區; LeaveCriticalSection()離臨界區 於線程共享內存東東講

(2)採用消息機制進行線程通信同步windows面消息機制函數用postmessageLinux消息機制我用較少說誰熟悉告訴我呵呵

(3)windows另外種線程通信事件信號量同針我始舉例2線程同步間傳遞信息採用事件(Event)或信號量(Semaphore),比第線程完產數據必須告訴第2線程已經數據准備取走第2線程數據取走呵呵採用消息機制第線程准備數據直接postmessage給第2線程按理說採用postmessage線程搞定問題呵呵重點省略講

於linux類似條件變數呵呵windowslinux同要特別講講才行

於windows採用事件信號量同步候都使用waitforsingleobject進行等待函數第參數句柄Event句柄或Semaphore句柄第2參數等待延遲終等久單位ms參數INFINITE限等待釋放信號量函數ReleaseSemaphore();釋放事件函數SetEvent使用些東西都要初始化講Msdn搜神馬都呵呵神馬都浮雲

於linux操作系統採用條件變數實現類似功能Linux條件變數般都互斥鎖起使用主要函數:

pthread_mutex_lock ,

pthread_mutex_unlock,

pthread_cond_init

pthread_cond_signal

pthread_cond_wait

pthread_cond_timewait

㈨ c#windows應用程序怎麼實現多線程

C#中的UI元素是主線程創建的,也只能通過創建它們的主線程進行修改,這是因為UI元素本身不是線程安全的,多線程操作會發生不可預料的錯誤。因此,默認情況下,嘗試從其他線程操作UI元素會引發異常,雖然你可以通過下面的代碼強制允許UI元素的跨線程操作:1
= false;

但是,這樣做是不推薦的。一般對於UI元素的跨線程操作推薦使用
1
2
Form.Invoke(Delegate method);
Form.Invoke(Delegate method, params object[] args);
Invoke方法可以由任何線程調用,但只會在創建Form的主線程上執行相應的Delegate。

一段最簡示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
private void button1_Click(object sender, EventArgs e)
{
new System.Threading.Thread(ThreadAction).Start(); //啟動線程
}
private void ThreadAction()
{
this.Invoke(new MethodInvoker(UIAction)); //在主線程上執行UIAction方法
}
private void UIAction()
{
this.Text = "Invoked"; //不會報錯
}
因為Invoke的參數包括Delegate委託,因此你需要根據要Invoke的方法的參數、返回值,定義對應的Delegate,然後才能調用。在上面的例子中,UIAction方法無參數、無返回,所以直接使用了MethodInvoker這個自帶的Delegate。

㈩ 淺談linux 多線程編程和 windows 多線程編程的異同

首先我們講講為什麼要採用多線程編程,其實並不是所有的程序都必須採用多線程,有些時候採用多線程,性能還沒有單線程好。所以我們要搞清楚,什麼時候採用多線程。採用多線程的好處如下:
(1)因為多線程彼此之間採用相同的地址空間,共享大部分的數據,這樣和多進程相比,代價比較節儉,因為多進程的話,啟動新的進程必須分配給它獨立的地址空間,這樣需要數據表來維護代碼段,數據段和堆棧段等等。
(2)多線程和多進程相比,一個明顯的優點就是線程之間的通信了,對不同進程來說,它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。但是對於多線程就不一樣了。他們之間可以直接共享數據,比如最簡單的方式就是共享全局變數。但是共享全部變數也要注意哦,呵呵,必須注意同步,不然後果你知道的。呵呵。
(3)在多cpu的情況下,不同的線程可以運行不同的cpu下,這樣就完全並行了。
反正我覺得在這種情況下,採用多線程比較理想。比如說你要做一個任務分2個步驟,你為提高工作效率,你可以多線程技術,開辟2個線程,第一個線程就做第一步的工作,第2個線程就做第2步的工作。但是你這個時候要注意同步了。因為只有第一步做完才能做第2步的工作。這時,我們可以採用同步技術進行線程之間的通信。
針對這種情況,我們首先講講多線程之間的通信,在windows平台下,多線程之間通信採用的方法主要有:
(1)共享全局變數,這種方法是最容易想到的,呵呵,那就首先講講吧,比如說吧,上面的問題,第一步要向第2步傳遞收據,我們可以之間共享全局變數,讓兩個線程之間傳遞數據,這時主要考慮的就是同步了,因為你後面的線程在對數據進行操作的時候,你第一個線程又改變了數據的內容,你不同步保護,後果很嚴重的。你也知道,這種情況就是讀臟數據了。在這種情況下,我們最容易想到的同步方法就是設置一個bool flag了,比如說在第2個線程還沒有用完數據前,第一個線程不能寫入。有時在2個線程所需的時間不相同的時候,怎樣達到最大效率的同步,就比較麻煩了。咱們可以多開幾個緩沖區進行操作。就像生產者消費者一樣了。如果是2個線程一直在跑的,由於時間不一致,緩沖區遲早會溢出的。在這種情況下就要考慮了,是不讓數據寫入還是讓數據覆蓋掉老的數據,這時候就要具體問題具體分析了。就此打住,呵呵。就是用bool變數控制同步,linux 和windows是一樣的。
既然講道了這里,就再講講其它同步的方法。同樣 針對上面的這個問題,共享全局變數同步問題。除了採用bool變數外,最容易想到的方法就是互斥量了。呵呵,也就是傳說中的加鎖了。windows下加鎖和linux下加鎖是類似的。採用互斥量進行同步,要想進入那段代碼,就先必須獲得互斥量。
linux上互斥量的函數是:
windows下互斥量的函數有:createmutex 創建一個互斥量,然後就是獲得互斥量waitforsingleobject函數,用完了就釋放互斥量ReleaseMutex(hMutex),當減到0的時候 內核會才會釋放其對象。下面是windows下與互斥的幾個函數原型。
HANDLE WINAPI CreateMutex(
__in LPSECURITY_ATTRIBUTES lpMutexAttributes,
__in BOOL bInitialOwner,
__in LPCTSTR lpName
);
可以可用來創建一個有名或無名的互斥量對象
第一參數 可以指向一個結構體SECURITY_ATTRIBUTES一般可以設為null;
第二參數 指當時的函數是不是感應感應狀態 FALSE為當前擁有者不會創建互斥
第三參數 指明是否是有名的互斥對象 如果是無名 用null就好。
DWORD WINAPI WaitForSingleObject(
__in HANDLE hHandle,
__in DWORD dwMilliseconds
);
第一個是 創建的互斥對象的句柄。第二個是 表示將在多少時間之後返回 如果設為宏INFINITE 則不會返回 直到用戶自己定義返回。
對於linux操作系統,互斥也是類似的,只是函數不同罷了。在linux下,和互斥相關的幾個函數也要閃亮登場了。
pthread_mutex_init函數:初始化一個互斥鎖;
pthread_mutex_destroy函數:注銷一個互斥鎖;
pthread_mutex_lock函數:加鎖,如果不成功,阻塞等待;
pthread_mutex_unlock函數:解鎖;
pthread_mutex_trylock函數:測試加鎖,如果不成功就立即返回,錯誤碼為EBUSY;
至於這些函數的用法,google上一搜,就出來了,呵呵,在這里不多講了。windows下還有一個可以用來保護數據的方法,也是線程同步的方式
就是臨界區了。臨界區和互斥類似。它們之間的區別是,臨界區速度快,但是它只能用來同步同一個進程內的多個線程。臨界區的獲取和釋放函數如下:
EnterCriticalSection() 進入臨界區; LeaveCriticalSection()離開臨界區。 對於多線程共享內存的東東就講到這里了。
(2)採用消息機制進行多線程通信和同步,windows下面的的消息機制的函數用的多的就是postmessage了。Linux下的消息機制,我用的較少,就不在這里說了,如果誰熟悉的,也告訴我,呵呵。
(3)windows下的另外一種線程通信方法就是事件和信號量了。同樣針對我開始舉得例子,2個線程同步,他們之間傳遞信息,可以採用事件(Event)或信號量(Semaphore),比如第一個線程完成生產的數據後,就必須告訴第2個線程,他已經把數據准備好了,你可以來取走了。第2個線程就把數據取走。呵呵,這里可以採用消息機制,當第一個線程准備好數據後,就直接postmessage給第2個線程,按理說採用postmessage一個線程就可以搞定這個問題了。呵呵,不是重點,省略不講了。
對於linux,也有類似的方法,就是條件變數了,呵呵,這里windows和linux就有不同了。要特別講講才行。
對於windows,採用事件和信號量同步時候,都會使用waitforsingleobject進行等待的,這個函數的第一個參數是一個句柄,在這里可以是Event句柄,或Semaphore句柄,第2個參數就是等待的延遲,最終等多久,單位是ms,如果這個參數為INFINITE,那麼就是無限等待了。釋放信號量的函數為ReleaseSemaphore();釋放事件的函數為SetEvent。當然使用這些東西都要初始化的。這里就不講了。Msdn一搜,神馬都出來了,呵呵。神馬都是浮雲!
對於linux操作系統,是採用條件變數來實現類似的功能的。Linux的條件變數一般都是和互斥鎖一起使用的,主要的函數有:
pthread_mutex_lock ,
pthread_mutex_unlock,
pthread_cond_init
pthread_cond_signal
pthread_cond_wait
pthread_cond_timewait
為了和windows操作系統進行對比,我用以下表格進行比較:

對照以上表格,總結如下:
(1) Pthread_cleanup_push,Pthread_cleanup_pop:
這一對函數push和pop的作用是當出現異常退出時,做一些清除操作,即當在push和pop函數之間異常退出,包括調用pthread_exit退出,都會執行push裡面的清除函數,如果有多個push,注意是是棧,先執行後面的那個函數,在執行前面的函數,但是注意當在這2個函數之間通過return 退出的話,執不執行push後的函數就看pop函數中的參數是不是為0了。還有當沒有異常退出時,等同於在這裡面return退出的情況,即:當pop函數參數不為0時,執行清除操作,當pop函數參數為0時,不執行push函數中的清除函數。
(2)linux的pthread_cond_signal和SetEvent的不同點
Pthread_cond_singal釋放信號後,當沒有Pthread_cond_wait,信號馬上復位了,這點和SetEvent不同,SetEvent是不會復位的。詳解如下:
條件變數的置位和復位有2種常用模型:第一種模型是當條件變數置位時(signaled)以後,如果當前沒有線程在等待,其狀態會保持為置位(signaled),直到有等待的線程進入被觸發,其狀態才會變為unsignaled,這種模型以採用Windows平台上的Auto-set Event 為代表。
第2種模型則是Linux平台的pthread所採用的模型,當條件變數置位(signaled)以後,即使當前沒有任何線程在等待,其狀態也會恢復為復位(unsignaled)狀態。
條件變數在Linux平台上的這種模型很難說好壞,在實際應用中,我們可以對
代碼稍加改進就可以避免這種差異的發生。由於這種差異只會發生在觸發沒有被線程等待在條件變數的時刻,因此我們只需要掌握好觸發的時機即可。最簡單的做法是增加一個計數器記錄等待線程的個數,在決定觸發條件變數前檢查該變數即可。
示例 使用 pthread_cond_wait() 和 pthread_cond_signal()
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count;
decrement_count()
{
pthread_mutex_lock(&count_lock);
while (count == 0)
pthread_cond_wait(&count_nonzero, &count_lock);
count = count - 1;
pthread_mutex_unlock(&count_lock);
}
increment_count()
{
pthread_mutex_lock(&count_lock);
if (count == 0)
pthread_cond_signal(&count_nonzero);
count = count + 1;
pthread_mutex_unlock(&count_lock);
}
(3) 注意Pthread_cond_wait條件返回時互斥鎖的解鎖問題
extern int pthread_cond_wait __P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));
調用這個函數時,線程解開mutex指向的鎖並被條件變數cond阻塞。線程可以被函數pthread_cond_signal和函數 pthread_cond_broadcast喚醒線程被喚醒後,它將重新檢查判斷條件是否滿足,如果還不滿足,一般說來線程應該仍阻塞在這里,被等待被下一次喚醒。如果在多線程中採用pthread_cond_wait來等待時,會首先釋放互斥鎖,當等待的信號到來時,再次獲得互斥鎖,因此在之後要注意手動解鎖。舉例如下:
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*初始化互斥鎖*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化條件變數
void *thread1(void *);
void *thread2(void *);
int i=1;
int main(void)
{
pthread_t t_a;
pthread_t t_b;
pthread_create(&t_a,NULL,thread1,(void *)NULL);/*創建進程t_a*/
pthread_create(&t_b,NULL,thread2,(void *)NULL); /*創建進程t_b*/
pthread_join(t_b, NULL);/*等待進程t_b結束*/
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
exit(0);
}
void *thread1(void *junk)
{
for(i=1;i<=9;i++)
{
printf("IN one\n");
pthread_mutex_lock(&mutex);//
if(i%3==0)
pthread_cond_signal(&cond);/*,發送信號,通知t_b進程*/
else
printf("thead1:%d\n",i);
pthread_mutex_unlock(&mutex);//*解鎖互斥量*/
printf("Up Mutex\n");
sleep(3);
}
}
void *thread2(void *junk)
{
while(i<9)
{
printf("IN two \n");
pthread_mutex_lock(&mutex);
if(i%3!=0)
pthread_cond_wait(&cond,&mutex);/*等待*/
printf("thread2:%d\n",i);
pthread_mutex_unlock(&mutex);
printf("Down Mutex\n");
sleep(3);
}
}
輸出如下:
IN one
thead1:1
Up Mutex
IN two
IN one
thead1:2
Up Mutex
IN one
thread2:3
Down Mutex
Up Mutex
IN one
thead1:4
Up Mutex
IN two
IN one
thead1:5
Up Mutex
IN one
Up Mutex
thread2:6
Down Mutex
IN two
thread2:6
Down Mutex
IN one
thead1:7
Up Mutex
IN one
thead1:8
Up Mutex
IN two
IN one
Up Mutex
thread2:9
Down Mutex
注意藍色的地方,有2個thread2:6,其實當這個程序多執行幾次,i=3和i=6時有可能多列印幾個,這里就是競爭鎖造成的了。
(4)另外要注意的Pthread_cond_timedwait等待的是絕對時間,這個和WaitForSingleObject是不同的,Pthread_cond_timedwait在網上也有討論。如下:這個問題比較經典,我把它搬過來。
thread_a :
pthread_mutex_lock(&mutex);
//do something
pthread_mutex_unlock(&mutex)
thread_b:
pthread_mutex_lock(&mutex);
//do something
pthread_cond_timedwait(&cond, &mutex, &tm);
pthread_mutex_unlock(&mutex)
有如上兩個線程thread_a, thread_b,現在如果a已經進入了臨界區,而b同時超時了,那麼b會從pthread_cond_timedwait返回嗎?如果能返回,那豈不是a,b都在臨界區?如果不能返回,那pthread_cond_timedwait的定時豈不是就不準了?
大家討論有價值的2點如下:
(1) pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *external_mutex, const struct timespec *abstime) -- This function is a time-based variant of pthread_cond_wait. It waits up to abstime amount of time for cv to be notified. If abstime elapses before cv is notified, the function returns back to the caller with an ETIME result, signifying that a timeout has occurred. Even in the case of timeouts, the external_mutex will be locked when pthread_cond_timedwait returns.
(2) 2.1 pthread_cond_timedwait行為和pthread_cond_wait一樣,在返回的時候都要再次lock mutex.
2 .2pthread_cond_timedwait所謂的如果沒有等到條件變數,超時就返回,並不確切。
如果pthread_cond_timedwait超時到了,但是這個時候不能lock臨界區,pthread_cond_timedwait並不會立即返回,但是在pthread_cond_timedwait返回的時候,它仍在臨界區中,且此時返回值為ETIMEDOUT。
關於pthread_cond_timedwait超時返回的問題,我也認同觀點2。
附錄:
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);
返回值:若成功則返回0,否則返回出錯編號
返回成功時,由tidp指向的內存單元被設置為新創建線程的線程ID。attr參數用於制定各種不同的線程屬性。新創建的線程從start_rtn函數的地址開始運行,該函數只有一個無指針參數arg,如果需要向start_rtn函數傳遞的參數不止一個,那麼需要把這些參數放到一個結構中,然後把這個結構的地址作為arg的參數傳入。
linux下用C開發多線程程序,Linux系統下的多線程遵循POSIX線程介面,稱為pthread。
由 restrict 修飾的指針是最初唯一對指針所指向的對象進行存取的方法,僅當第二個指針基於第一個時,才能對對象進行存取。對對象的存取都限定於基於由 restrict 修飾的指針表達式中。 由 restrict 修飾的指針主要用於函數形參,或指向由 malloc() 分配的內存空間。restrict 數據類型不改變程序的語義。 編譯器能通過作出 restrict 修飾的指針是存取對象的唯一方法的假設,更好地優化某些類型的常式。
第一個參數為指向線程標識符的指針。
第二個參數用來設置線程屬性。
第三個參數是線程運行函數的起始地址。
第四個參數是運行函數的參數。
因為pthread不是linux系統的庫,所以在編譯時注意加上-lpthread參數,以調用靜態鏈接庫。
終止線程:
如果在進程中任何一個線程中調用exit或_exit,那麼整個進行會終止,線程正常的退出方式有:
(1) 線程從啟動常式中返回(return)
(2) 線程可以被另一個進程終止(kill);
(3) 線程自己調用pthread_exit函數
#include
pthread_exit
線程等待:
int pthread_join(pthread_t tid,void **rval_ptr)
函數pthread_join用來等待一個線程的結束。函數原型為:
extern int pthread_join __P (pthread_t __th, void **__thread_return);
第一個參數為被等待的線程標識符,第二個參數為一個用戶定義的指針,它可以用來存儲被等待線程的返回值。這個函數是一個線程阻塞的函數,調用它的函數將一直等待到被等待的線程結束為止,當函數返回時,被等待線程的資源被收回。
對於windows線程的創建東西,就不列舉了,msdn上 一搜就出來了。呵呵。今天就講到這里吧,希望是拋磚引玉,大家一起探討,呵呵。部分內容我也是參考internet的,特此對原作者表示感謝!

熱點內容
不用internet打開ftp 發布:2025-05-15 23:06:00 瀏覽:152
sql字元串取數字 發布:2025-05-15 22:57:45 瀏覽:124
推薦編程課 發布:2025-05-15 22:34:12 瀏覽:618
表拒絕訪問 發布:2025-05-15 22:29:37 瀏覽:978
電腦怎樣解壓文件 發布:2025-05-15 22:25:32 瀏覽:439
dns伺服器怎麼看 發布:2025-05-15 22:17:27 瀏覽:151
3dm的壓縮包 發布:2025-05-15 22:09:23 瀏覽:662
和存儲字長 發布:2025-05-15 21:54:09 瀏覽:515
用什麼寫c語言 發布:2025-05-15 21:35:56 瀏覽:418
linux讀取u盤 發布:2025-05-15 21:32:13 瀏覽:508