首页 > 其他分享 >多线程同步篇

多线程同步篇

时间:2022-12-21 13:44:08浏览次数:35  
标签:同步 计数 访问 互斥 线程 内核 多线程 资源

用户模式下的线程同步

原子访问

指的是一个线程在访问某个资源的同时能保证没有其他线程会在统一时刻访问同一资源。传入的变量必须是经过内存对齐的

InterlockedExchangeAdd/InterlockedExchangeAdd64:给传入的值增长传入的增量

InterlockedIncrement:给传入的值增1

InterlockedExchange/InterlockedExchangePointer:把第一个参数所指向的地址的当前值替换为第二个参数指定的值。在32位应用程序与InterlockedExchangePointer一样读书用32值替换另一个值,对于64位程序InterlockedExchange替换32位的值,InterlockedExchangePointer替换64位的值。函数会返回参数原来的值

关键段

关键段是一小段代码,它在执行之前需要独占对一些共享资源发访问权。内部使用计数器来记录访问该资源权限的次数,可以多次进入关键段。如果当前资源已经有一个线程获得访问权,会使用一个事件内核对象把调用线程切换到等待状态,在等待中的线程不会浪费任何cpu时间。

关键段内部有一个自旋锁,当尝试一段时间不能获取资源的访问权后依旧不能获得权限后,线程会切换到内核模式并进入等待状态。自旋锁的尝试次数可以设置。

Slim读写锁

SRWLock允许我们区分想要读数据和想要更新数据的线程,让所有读线程在同一时刻访问共享资源,只有当写入线程进行访问时才需要进行同步。写入线程会独占对资源的访问权。

条件变量

让线程以原子方式把锁释放并将自己堵塞,直到某一个条件成立为止。

性能对比

Volatile>Interlocked>SRWLock>关键段>内核模式

自旋锁

在while的判定中把值设置为true,并以参数原来的值与true进行比较,如果没有在其他地方设置为true,那么线程将一直被睡眠。

内核模式线程同步

WaitForSingleObiect

线程主动进入等待状态,直到指定的内核对象被触发为止。

事件

包含一个使用计数,一个用来表示事件是否自动重置的布尔值,以及另一个用来表示事件有没有触发的布尔值。 其他进程可以通过创建或打开事件,传入相同名称来访问该事件对象。

事件的触发表示一个事件已经完成。有手动重置事件和自动重置事件,

当手动重置事件被触发的时候,正在等待该事件的所有线程读将变成可调度状态,当自动重置事件被触发的时候,只有一个正在等待该事件的线程会变成可调度状态。

可等待计时器:会在某个指定时间或每隔一段时间触发一次。

信号量

包含一个使用计数,一个32位的最大资源计数,一个32位的当前资源计数,最大资源计数表示信号量可以控制的最大资源数量,当前资源计数表示信号量当前可用资源的数量。

线程调用一个等待函数并传入信号量句柄,在内部,等待函数会检测信号量的当前资源计数,如果值大于0,那么函数会把资源计数减一并让调用线程继续执行。信号量的最大优势在于它们会以原子的方式来执行这次额测试和设置操作,只有当资源计数递减后,系统才会允许另一个线程访问资源。

信号量一般用于管理线程的调度,而不是对一个具体资源的访问权保护。

互斥量

用来确保一个线程独占一个资源的访问,互斥量对象包含一个使用计数,线程id已经一个递归计数。

线程id用来标识当前占用这个互斥量的是系统的哪个线程

递归计数用来标识占用该互斥量的次数

如果线程id为无效的线程id(0),那么该互斥量不为任何线程占用,它处于触发状态,反之有一个线程占用了该互斥量,它处于触发状态。

互斥量于关键段的行为完全相同。

在用来触发通内核对象和撤销触发普通内核对象的规则中,有一条不适用于互斥量。假设线程试图等待一个未触发的互斥量对象。在这种情况下,线程通常会进入等待状态。但是,系统会检查想要获得互斥量的线程的线程ID与斥量对象内部记录的线程ID是否相同。如果线程ID一致,那么系统会让线程保持可调度状态一一即使该互斥量尚未触发。对系统中的任何其他内核对象来说,我们都找不到这种“异常”的举动。每次线程成功地等待了一个互斥量,互斥量对象的递归计数会递增。使递归计数大于 1的唯一途径是利用这个例外,让线程多次等待同一个互斥量。

个人理解:一个资源被一个占用的时候,会检查等待线程的线程ID,当等待的线程与当前独占资源的线程相同的时候(id一致,线程也一致),那么被等待线程可以共享该资源。

如果互斥量的线程在释放互斥量之前被终止,那么系统会认为互斥量被遗弃,无法在释放这个对象。

用户模式线程同步和内核模式线程同步的区别

1.内核模式同步会创建一个内核对象,用户模式只是使用原子方式

2.用户模式性能比内核模式更高很多

3.不同进程可以访问内核模式的对象,线程可以等待对资源访问时指定一个最长等待时间

标签:同步,计数,访问,互斥,线程,内核,多线程,资源
From: https://www.cnblogs.com/zjr0/p/16995961.html

相关文章