当前位置:首页 » 编程软件 » 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的,特此对原作者表示感谢!

热点内容
dmporacle数据库 发布:2025-05-16 02:44:31 浏览:829
云主机上传 发布:2025-05-16 02:44:30 浏览:80
鼠标如何编程 发布:2025-05-16 02:29:09 浏览:816
安卓70能用什么软件 发布:2025-05-16 01:45:09 浏览:480
编程发展史 发布:2025-05-16 01:38:52 浏览:529
android图片气泡 发布:2025-05-16 01:38:40 浏览:886
文件加密编辑器下载 发布:2025-05-16 01:30:41 浏览:343
linuxapacheyum安装 发布:2025-05-16 01:30:31 浏览:476
大连宾利浴池wifi密码是多少 发布:2025-05-16 01:25:36 浏览:172
缓存数据生产服务 发布:2025-05-16 01:08:58 浏览:585