015 原子操作 旋转锁

以下代码个别情况下会出错 导致值为1

#define UNICODE
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <process.h>

long gNum = 0;
unsigned int __stdcall ThreadRun1(void* lParam)
{
    //锁
    //原子操作
    //同一资源在同一时间只有一个线程能够访问
    //系统级的操作
    //在硬件里面设置了一些局限性
    InterlockedExchangeAdd(&gNum,1);
//    gNum += 1;
    return 0;
}

unsigned int __stdcall ThreadRun2(void* lParam)
{
    InterlockedExchangeAdd(&gNum,1);
    //gNum += 1;
    return 0;
}
int main()
{
    HANDLE hThread[2];
    hThread[0] = (HANDLE)_beginthreadex(nullptr,0,ThreadRun1,nullptr,0,nullptr);
    hThread[1] = (HANDLE)_beginthreadex(nullptr,0,ThreadRun2,hThread[0],0,nullptr);
    WaitForMultipleObjects(sizeof(hThread)/sizeof(HANDLE), hThread,TRUE, INFINITE);
    printf("gNum:%d",gNum);
    for(int i = 0; i<sizeof(hThread)/sizeof(HANDLE);++i)
    {
        CloseHandle(hThread[i]);
    }
    return 0;
}
#define UNICODE
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <process.h>

long gNum = 0;
unsigned int __stdcall ThreadRun1(void* lParam)
{
    //锁
    //原子操作
    //同一资源在同一时间只有一个线程能够访问
    //系统级的操作
    //在硬件里面设置了一些局限性    gNum += 1;
    return 0;
}

unsigned int __stdcall ThreadRun2(void* lParam)
{gNum += 1;
    return 0;
}
int main()
{
    HANDLE hThread[2];
    hThread[0] = (HANDLE)_beginthreadex(nullptr,0,ThreadRun1,nullptr,0,nullptr);
    hThread[1] = (HANDLE)_beginthreadex(nullptr,0,ThreadRun2,hThread[0],0,nullptr);
    WaitForMultipleObjects(sizeof(hThread)/sizeof(HANDLE), hThread,TRUE, INFINITE);
    printf("gNum:%d",gNum);
    for(int i = 0; i<sizeof(hThread)/sizeof(HANDLE);++i)
    {
        CloseHandle(hThread[i]);
    }
    return 0;
}

出错的原因

下面是加硬件锁代码

 1 #define UNICODE
 2 #include <stdio.h>
 3 #include <tchar.h>
 4 #include <windows.h>
 5 #include <process.h>
 6
 7 long gNum = 0;
 8 unsigned int __stdcall ThreadRun1(void* lParam)
 9 {
10     //锁
11     //原子操作
12     //同一资源在同一时间只有一个线程能够访问
13     //系统级的操作
14     //在硬件里面设置了一些局限性
15     InterlockedExchangeAdd(&gNum,1);
16 //    gNum += 1;
17     return 0;
18 }
19
20 unsigned int __stdcall ThreadRun2(void* lParam)
21 {
22     InterlockedExchangeAdd(&gNum,1);
23     //gNum += 1;
24     return 0;
25 }
26 int main()
27 {
28     HANDLE hThread[2];
29     hThread[0] = (HANDLE)_beginthreadex(nullptr,0,ThreadRun1,nullptr,0,nullptr);
30     hThread[1] = (HANDLE)_beginthreadex(nullptr,0,ThreadRun2,hThread[0],0,nullptr);
31     WaitForMultipleObjects(sizeof(hThread)/sizeof(HANDLE), hThread,TRUE, INFINITE);
32     printf("gNum:%d",gNum);
33     for(int i = 0; i<sizeof(hThread)/sizeof(HANDLE);++i)
34     {
35         CloseHandle(hThread[i]);
36     }
37     return 0;
38 }
 1 #define UNICODE
 2 #include <stdio.h>
 3 #include <tchar.h>
 4 #include <windows.h>
 5 #include <process.h>
 6
 7 long gNum = 0;
 8 BOOL bUseing = FALSE;
 9
10 //线程的饥饿
11 //线程优先级
12 //CPU
13 //调度区
14 //        1        31
15 //        2        31
16 //        3        30        饥饿 可能永远得不到执行
17 unsigned int __stdcall ThreadRun1(void* lParam)
18 {
19     //锁
20     //原子操作
21     //同一资源在同一时间只有一个线程能够访问
22     //系统级的操作
23     //在硬件里面设置了一些局限性
24     while(InterlockedExchange((long*)&bUseing, TRUE) != TRUE)    //旋转锁
25         Sleep(0);
26
27     //.....        上锁后的代码  线程安全 绝对安全的
28     InterlockedExchange((long*)&bUseing, FALSE);
29 //    gNum += 1;
30     return 0;
31 }
32
33 unsigned int __stdcall ThreadRun2(void* lParam)
34 {
35     //InterlockedExchangeAdd(&gNum,1);
36     //gNum += 1;
37     while(InterlockedExchange((long*)&bUseing, TRUE) != TRUE)
38     Sleep(0);
39
40     //.....        上锁后的代码  线程安全
41
42     InterlockedExchange((long*)&bUseing, FALSE);
43     return 0;
44 }
45 int main()
46 {
47     HANDLE hThread[2];
48     hThread[0] = (HANDLE)_beginthreadex(nullptr,0,ThreadRun1,nullptr,0,nullptr);
49     hThread[1] = (HANDLE)_beginthreadex(nullptr,0,ThreadRun2,hThread[0],0,nullptr);
50     WaitForMultipleObjects(sizeof(hThread)/sizeof(HANDLE), hThread,TRUE, INFINITE);
51     printf("gNum:%d",gNum);
52     for(int i = 0; i<sizeof(hThread)/sizeof(HANDLE);++i)
53     {
54         CloseHandle(hThread[i]);
55     }
56     return 0;
57 }
时间: 2024-10-13 00:22:18

015 原子操作 旋转锁的相关文章

多线程计数器——原子操作

众所周知,多线程下计数存在着计数不正确的问题.这个问题的根源在于多个线程对同一个变量可以同时访问(修改).这样就造成了修改后的结果不一致. 首先在这里先强调一点,volatile 关键字并不能提供多线程安全访问.因为有volatie修饰的变量,每次操作时遵循下面动作: 从内存取值 ---> 放入寄存器 ---> 操作 --->写回内存 这几个步骤不是原子的操作在任意两个步骤之间都可能被其他的线程中断,所以不是线程安全.详细内容参见 http://blog.csdn.net/littlef

第8章 用户模式下的线程同步

8.1 原子访问:Interlocked系列函数(Interlock英文为互锁的意思) (1)原子访问的原理 ①原子访问:指的是一线程在访问某个资源的同时能够保证没有其他线程会在同一时刻访问该资源. ②从汇编的角度看,哪怕很简单的一条高级语言都可以被编译成多条的机器指令.在多线程环境下,这条语句的执行就可能被打断.而在打断期间,其中间结果可能己经被其他线程更改过,从而导致错误的结果. ③在Intelx86指令体系中,有些运算指令加上lock前缀就可以保证该指令操作的原子性.其原理是CPU执行该指

windows基础复习

1.1.命令提示符(控制台)是一个软件:如果你的软件设置为控制台用户界面,那么Window会拿命令提示行来运行你的软件. 1.2.如果是窗口的话,Windows就不会来管你,就只是直接加载. 1.3.hPrevInstance:在你的程序中永远都不要使用. 1.4.进程实例句柄:加载到地址空间的每一个执行体或者DLL文件都被赋予了一个独一无二的实例句柄. 1.5.进程在死亡的时候我们需要做一些回收和清理的事情. 1.6.内核对象泄露是会比内存泄露更加麻烦的事情.内存泄露可以通过关闭进程来解决,而

【WIN32进阶之路】:线程同步技术纲要

前面博客讲了互斥量(MUTEX)和关键段(CRITICAL SECTION)的使用,想来总觉不妥,就如盲人摸象一般,窥其一脚而言象,难免以偏概全,追加一篇博客查遗补漏. win32下的线程同步技术分为用户模式下的线程同步和用内核对象进行线程同步两大类. 用户模式下的线程同步和用内核对象进行线程同步有以下的明显差异: 1.用户模式下的线程同步不需要进入操作系统核心,直接在用户模式就可以进行操作. 2.用内核对象进行线程同步需要进入操作系统核心,用户模式切换至核心模式大约花费1000个CPU周期.

Windows核心编程笔记(6)----用户模式下的线程同步

1.原子锁 使用InterlockedExchangeAdd函数来实现原子增长,InterlockedExchange\InterlockedExchangePointer用来交换两个变 量的值,InterlockedCompareExchange对比数值,相等则交换(对应的InterlockedCompareExchangePointer).对应的 还有64位函数. InterlockedIncrement\InterlockedDecrement是比较老的函数,只能增加或递减1,Interl

WINDOWS 同步(Interlocked,InterlockedExchangeAdd,Slim读/写锁,WaitForSingleObject,CreateWaitableTimer等等)

NOTE0 在以下两种基本情况下,线程之间需要相互通信: 需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性: 一个线程需要通知其它线程某项任务已经完成 1.原子访问:Interlocked系列函数 http://hi.baidu.com/microsoftxiao/blog/item/a6411546296bc90c6a63e561.html该文章不错.    所谓原子访问,指的是一个线程在访问某个资源的同时能够保证没有其他线程会在同一时刻访问同一资源.     我们需要有一种方法能

【JUC】JDK1.8源码分析之ConcurrentHashMap(一)

一.前言 最近几天忙着做点别的东西,今天终于有时间分析源码了,看源码感觉很爽,并且发现ConcurrentHashMap在JDK1.8版本与之前的版本在并发控制上存在很大的差别,很有必要进行认真的分析,下面进行源码分析. 二.ConcurrentHashMap数据结构 之前已经提及过,ConcurrentHashMap相比HashMap而言,是多线程安全的,其底层数据与HashMap的数据结构相同,数据结构如下 说明:ConcurrentHashMap的数据结构(数组+链表+红黑树),桶中的结构

秒杀多线程第五篇 经典线程同步 关键段CS

版权声明:本文为博主原创文章,未经博主允许不得转载. 上一篇<秒杀多线程第四篇 一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,本篇将用关键段CRITICAL_SECTION来尝试解决这个问题. 本文首先介绍下如何使用关键段,然后再深层次的分析下关键段的实现机制与原理. 关键段CRITICAL_SECTION一共就四个函数,使用很是方便.下面是这四个函数的原型和使用说明. 函数功能:初始化 函数原型: void InitializeCriticalSection(LPCRITIC

为不同版本的 Windows 编写驱动程序

MSDN原文:https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff554887(v=vs.85).aspx 创建驱动程序项目时,指定基本的目标操作系统,该系统是运行驱动程序的基本版本的 Windows.例如,你可以指定 Windows 7 为基本的目标操作系统.在这种情况下,驱动程序会在 Windows 7 和更高版本的 Windows 上运行. 注意  如果为特定的基本版本的 Windows 开发驱动程序且希望驱动程序运行在更