U盘PE| w764位旗舰版下载 | U盘装win7系统 | U盘启动 |win7pe | win10下载 |加入收藏土豆PE官网U盘PE,U盘装win7系统,win7pe,U盘启动,U盘装系统,w764位旗舰版下载站!
当前位置:主页 > 帮助中心 > 常见问题解答 >

Windows程序设计学习笔记——线程(二)同步

来源:http://www.tudoupe.com时间:2022-07-30

一、同步问题概述

如果多个线程同时读写到相同的变量(内存区),结果将与线程转换的结果(计算机时间表分配)不符,如果两个线程A和B同时执行变量自增操作,因为A从内存数据转换为CPU,然后从线程转换为B,B取完数据,在Cpu操作完成后,结果被写回记忆中,线程被转换为A,A继续从中断位置执行,即计算和写回记忆,这使得A和B返回相同的记忆结果,也就是说,它是一个变量的自增的结果,而不是两个自加操作的结果,这就是同步问题

如图:

运行结果:

用户模式下的解决方案

1.原子(相互锁定)操作

原子操作是未被线程时间表中断的操作,并不会在操作中引起线程开关的操作。窗口提供的原子操作API如下:

以自增运算为例:

演示:

运行结果:

第一个可以看到多次运行的线程的值总是在变化,这是因为在执行这些原子操作时,线程不断交换,所以第一个线程的值总是不固定,但是它总是大于1,00,00,最后的变量是2,00,00,相当于在循环中执行两次

2.临界区

如果我们的操作不是自加,而是如下:

编译后,你会发现它不能运行,并且中断位置没有固定,像这样

原子操作api仅用于简单的操作,当操作更加复杂时,我们可以使用一个关键区域,相当于锁定,锁定代码,只允许当前线程访问,其他线程将被锁定, relatedapi:

进入关键区域(上锁):

参数是一个结构指向下述结构的指针

这个机构的成员不需要由我们填补,而是由我们自己填补

出临界区(开锁):

临界区初始化:

临界区反初始化

示例:

三、内核同步对象

由Windows内核提供,可以使用0环和3环

1.互斥体

与内核版本相符的临界区域可以在整个进程中使用

创建或打开互斥体:

注意,如果第二个参数是 TRUE,并且调用者创建了相互锁,调用者线程获得相互体的初始所有权

补充:虽然每个过程都有自己的独立资源和空间,但是有时候,我们只是需要这个程序在系统上保存一个进程的实例,这就是过程互惠的问题。CreateMutex函数的第三个参数可以指定对象的名称,每次一个程序运行时,系统是否存在同一个名称的相互厌恶对象,以确定该程序是否重复运行。如果有相同名称的对象,GetLastError()函数返回 ERROR_ALREADY_EXISTS

锁定相互对象(同样用于等待一个线程或进程结束):

如果互斥体未锁上,则该函数将上锁,否则将处于阻塞状态,第二个参数表示超时时间,如果过了这个时间,锁仍然未开,则函数将退出,但是如果这个时间内锁开了,函数也会退出,可以根据返回值来判断是哪种情况退出:

WAIT_OBJECT_0
0x00000000L

锁开了

WAIT_TIMEOUT
0x00000102L

锁未开,超时了

WAIT_ABANDONED
0x00000080L

确定使用相互厌恶实体的线程是否终止

解锁(将线程的控制权释放到相互排除的对象):

示例:

关键区域与相互厌恶的机构之间的区别:

对于互斥体来说,当上锁的线程结束了并且没有开锁,锁会自动开,这种开锁称为线程遗弃,而对于临界区,当上锁的线程结束了并且没有开锁,锁不会自动开,其他线程依然处于阻塞状态

2.事件

创建事件内核对象:

第二个参数确定是否自动解锁,或者是否调用api来解锁自己

第三个参数表明您不应该解锁初始状态

上锁/等待:

锁定(设置事件对象触发):

上锁(将事件对象设置为未触摸):

示例:

3.信号量

信号数量和前面的临界区域,相互厌恶等等,都是不同的,临界区,复合是专用CPU资源,信号数量用于限制同时运行的线程数目。信号量内核对象中有一个最大资源计数和一个当前资源计数,最大资源计数表示信号量可以控制的最大资源数目,当前资源计数表示当前资源可用信号的数目。

创建信号量:

增加信号个数:

如果当前资源计数大于0,那么信号量处于触发状态,如果当前资源计数等于0,那么信号量处于未触发状态。当一个线程访问资源时,当前资源计数会减一,但是当前资源计数一定大于等于0并且小于最大资源计数

使用:

运行结果:

补充:

对线程同步来说,每个核对象有两个状态,要么处于触发/有信号(signaled)状态,要么处于未触发/无信号(nonsignaled)状态,每种对象都有相应规则在这两个状态中切换,如果进程内核对象在创建时总是处于未触摸的状态,当进程终止时,该进程的内核对象由操作系统设置为触发状态。对于线程来说,如果线程等待的对象处于未触摸的状态,在这一点上,这条线是不可逆转的,当对象处于触发状态时,只有线程可以转换为模块化,上述WaitForSingleObject函数是一个等待函数,将允许一个线程单独进入等待状态,直到指定的内核对象被触发或在一段时间内.

锁实际上是一个等待对象被触发的线程,然后被锁定,打开锁是为了让对象被触发

等待多个对象可以调用下列API:

Copyright © 2012-2014 Www.tudoupe.Com. 土豆启动 版权所有 意见建议:tdsky@tudoupe.com

土豆系统,土豆PE,win7系统下载,win7 64位旗舰版下载,u盘启动,u盘装系统,win10下载,win10正式版下载,win10 RTM正式版下载,win8下载,电脑蓝屏,IE11修复,网络受限,4K对齐,双系统,隐藏分区,系统安装不了,U盘装系统,笔记本装系统,台式机装系统,diskgenius运用,GHSOT装系统,U盘修复,U盘技巧,U盘速度,U盘不能格式化,U盘复制发生错误,U盘加密,U盘选购,开机黑屏,蓝屏,进不了系统,上不了网,打不开程序,点击无反应,系统设置,PE个性化,PE添加网络,PE维护系统

点击这里给我发消息