天天看点

Windows下多线程数据同步互斥的有关知识



对于操作系统而言,在并行程序设计中难免会遇到数据同步和共享的问题,本文针对这个问题,以windows系统为例回顾一下资源同步的相关问题。要点如下:

1.同步和数据共享

 数据征用

2.同步原语

    1.互斥和临界区

    2.自旋锁

    3.信号量

    4.读写锁

    5.屏障

    6.原子操作与无锁代码

3.进程和进程间通信

    1.共享内存和映射文件

    2.条件变量

    3.信号和事件

    4.消息队列

    5.命名管道

    6.socket网络栈

知识点:句柄

许多windows API函数都返回句柄。句柄只是无符号整数,但却有特殊的用途。返回句柄的windows API 调用实际上是在内核空间创建某个资源,句柄只是这个资源的索引。当应用程序使用完该资源后,就可调用CloseHandle()使内核释放相关的内核空间资源。

创建线程的3种不同的方式

       调用_beginthread()是个吸引人的选择,这个函数的参数较少,并且在线程退出后清除句柄。但是,如果线程终止,则_beginthread()调用返回的句柄将是无效的,或是被重用的,因此无法查询线程的状态,甚至无法肯定线程句柄是最初指向同一线程的句柄。

Windows下多线程数据同步互斥的有关知识

加上getchar()的区别

Windows下多线程数据同步互斥的有关知识

判断一个数是否为素数:

#include<math.h>

int isprime(int number)

{

int i;

for( i = 2; i < (int) (sqrt((float)number) + 1.0); i++)

    if(number % i == 0 ){ return 0;}

}

return 1;

测试给定范围内数字是否为素数的算法,如果两个线程同时访问变量counter,这将导致数据征用,正确的代码需要对递增变量counter的操作进行保护。

volatile int counter = 0;

unsigned int __stdcall test(void *)

while(counter < 100)

    int number = counter++;

//c++格式话输出要用cout对象的方法来控制

    printf("ThreadID %i value = %i    is prime  = %i  \n", GetCurrentThreadId(), number , isprime(number) );

return 0;

1.保护对临界区代码的访问:

// testofCriticalSection.cpp : 定义控制台应用程序的入口点。

//

Windows下多线程数据同步互斥的有关知识

使线程休眠然后再唤醒线程非常耗时,因为这涉及进入内核。所有临界区在设计上都应保证耗时尽可能短。要谨记,很可能线程进入休眠时,原处于临界区的线程已经离开。因此,令等待线程休眠后再唤醒浪费了很多时间。

有两种选择解决上述问题:

1.使用TryEnterCriticalSection()避免让调用线程休眠

2.面向临界区设定旋转计数的方法

InitializeCriticalSetionAndSpinCount( &critical,1000)

SetCriticalSectionSpinCount( &critical, 1000)

参考文献:

戈夫. 多核应用编程实战[M]. 人民邮电出版社, 2013.