线程(二)

本文探讨了线程同步的重要性和实现方法,包括线程的上下文切换、暂停与恢复,以及如何通过原子操作避免资源冲突。介绍了关键代码段的使用及限制,并对比了用户级同步与内核级同步的特点。
 
 
1) 线程的上下文切换
2)暂停的线程不可以调度。等待事件发生的线程也不能调度。
       内核对象内有一个值,指明线程的暂停计数。当值为0时可以调度。
SuspendThread(hThread);
ResumeThread(hThread);
3)计算线程执行时间
4)结构环境
G e t T h r e a d C o n t e x tS e t T h r e a d C o n t e x t函数使你能够对线程进行许多方面的控制,但是在使用它们时应该小心。实际上,几乎没有应用程序调用这些函数。增加这些函数是为了增强调试程序和其他工具的功能。任何应用程序都可以调用它们。
 
线程同步用户方式
1何时需要同步
当有多个线程访问共享资源而不使资源被破坏时。
当一个线程将一个任务已完成的情况通知一个或多个线程时。
2)原子访问
线程在访问资源时确保所有其它线程不在相同时间内访问同一资源。
Long g_x = 0;
 
DWORD WINAPI ThreadPro1(PVOID pvParam)
{
       G_x ++;
       Return 0;
}
 
DWORD WINAPI ThreadPro2(PVOID pvParam)
{
G_x++;
       Return 0;
}
上述在真正执行时变为下列汇编语句:
Mov eax [g_x]
Inc eax
Mov [g_x] eax
 
Mov eax [g_x]
Inc eax
Mov [g_x] eax
 
但是由于Windows 是抢占式调度方式,上述期待执行顺序可能变为
 
Mov eax [g_x]
Inc eax
 
Mov eax [g_x]
Inc eax
 
Mov [g_x] eax
Mov [g_x] eax
所以最后结果不是期待的 2 而是1 。所以需要同步。
 
 
我们需要保证上述递增的操作已原子方式进行,而不是中断的运行。
So we hope that the operation of increment above should run at atom way.not being interrupted.
 
InterlockedExchangeAdd()之类函数可以解决原子访问问题。
 
3)高速缓存行 in order to improve cpu running performance
4)关键代码段缺点:无法对多个进程中的线程进行同步
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
DeleteCriticalSection(&cs);
 
EnterCriticalSection(&cs);
LeaveCriticalSection(&cs);
 
循环锁 InitializeCriticalSectionAndSpinCount(&cs , dword )使线程等待之前它要获得资源使循环锁迭代次数。双cpu
 
       使用技巧:
每个共享资源使用一个Critical_Section 变量
Int g_num[100];
Critical_Section g_csnum;
Int g_char[100];
Critical_Section g_cschar;
B 同时访问多个共享资源
 
EnterCriticalSection(&g_csnum);
EnterCriticalSection (&g_cschar);
G_num[];
G_char[] ;
LeaveCriticalSection(&g_cschar);
LeaveCriticalSection(&g_csnum);
 
EnterCriticalSection (&g_cschar);
EnterCriticalSection(&g_csnum);
G_num[];
G_char[] ;
LeaveCriticalSection(&g_csnum);
LeaveCriticalSection(&g_cschar);
 
有可能发生死锁,必须按照相同的请求对资源进行访问
 
C 不要长时间运行关键代码段。
SomeStruct gss;
CriticalSection cs;
 
EnterCriticalSection(&cs);
SendMessage(&gss);
LeaveCriticalSection(&cs);
 
无法确定 SendMessage 运行多久,所以最好使用下面代码:
EnterCriticalSection(&cs);
SomeStruct temp gss;
LeaveCriticalSection(&cs);
SendMessage(temp)
用户方式同步 1 2 关键代码段
 
线程与内核对象同步
1 用户方式线程同步速度快,关键代码段只能对单个进程中线程同步。锁只能对单值,无法使线程进入等待模式。
2 线程可以使自己进入等待状态,直到一个对象进入已通知状态。
    当线程等待的对象处于未通知状态,线程不可调度。
    当线程等待的对象处于已通知状态,线程可以调度。
3 下面内核对象可以处于已通知状态和未通知状态。
    进程线程作业事件可等待计时器文件修改通知文件控制台输入  
    信标互斥对象
4        等待函数 可使线程进入等待状态,直到一个特定的内核对象变成已通知状态。
DWORD WaitforSingleObject(HANDLE handle,dword dwmilliseconds);//等待对象,等待时间  infinite 等待无限时间
返回值 wait_object_0 等待对象变为已通知状态
Wait_timeout 超时
Wait_failed 错误的值
Dword WaitforMultipleObjects(dword dwcount , //等待多少对象
Const Handle *h,//对象地址
Bool   waitall);//是否等待全部对象变为已通知
Dword millisecond);//等待时间
如果waitall true 则等待所有对象,返回与上相同
如果waitall false 则不是等待所有对象。返回值如果不是wait_timeout wait_failed 则返回值是wait_object_0 wait_object_0+dwcount -1之间的值
 
5        成功等待的副作用 函数返回之前,事件被设置成未通知状态。
6         事件内核对象最基本的内核对象。包含一个使用计数,一个指明事件是自动重置还是人工重置事件,一个指明是已通知还是未通知的事件。(待续)
 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值