技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152
还是用上次的工程
把代码copy到vs中
CreateMutex这个是个系统默认核心对象,这个第一个参数,LPSECURITY_ATTRIBUTES,肯定是需要的
这里我们用默认安全级别,填写NULL就可以.
这个bInitialOwner,一般是填写false,就是这个互斥锁是共享的,
填写true就是说这个互斥锁被当前这个线程所拥有,不过这里填写true,false一般没有什么区别.
第三个是,这互斥器的名字.通过这个名字,可以在一个进程中创建互斥器,在另一个进程中打开互斥器.
因为我们这里不涉及到多个进程间通信使用,所以这里第三个参数我们传递NULL
可以看到这个函数如果返回的是NULL,说明出现了错误,可以通过GetLastError这个函数,来获取错误信息
然后如果返回的是
返回的是这个ERROR_ALREADY_EXISTS的话,那么说明这个互斥器就已经存在了
这里在创建线程按钮中,启动50个线程.
然后
然后线程函数中去使用这个互斥器,使用的时候
要在给字符串数组添加元素的时候,首先使用互斥器,进行等待.
WaitForSingleObject(ghMutex,INFINITE)
这个函数
这个WaitForSingleObject这个互斥器,第一个参数是哪个互斥器的句柄
这里定义了一个互斥器句柄.
第二个参数是,多长时间超时.
比如来了一个线程,去执行,这个往字符串数组中添加元素,这个时候先执行
WaitForSingleObject这个函数,执行的时候,会获取到一个结果,就是说,
别的线程有没有正在添加元素,如果正在操作的话,这个就会返回一个waitfor,就是返回需要等待的一个标志
如果没有别的线程正在操作的话,就可以直接进入了给字符串数组添加元素了.
这INFINITE这个是默认的超时时间.1000,就是1s,毫秒为单位.
这个WAIT_OBJECT_0意思就是说,被保护的代码,目前没有被其他线程使用,现在
可以使用这部分代码
另外如果返回WAIT_ABANDONED这个是什么意思呢?
上节课说的用Critical Sections的时候,咱们说如果执行了EnterCritical,但是还没有来得及执行
LeaveCritical,接着这个线程就结束了,导致,被锁的部分代码,就被锁住了,别的线程就不能用了,没有解决办法.
这里用这互斥锁mutex就可以解决了,
这里有个WAIT_ABANDONED,就是说,如果某个线程,调用WaitForSingleObject等待的时候,还没有来得及
releaseMutex就结束了,这样这里获取的这个WaitResult就会是WAIT_ABANDONED,这样就能处理这种情况了.
然后用完以后要记得releaseMutex(ghMutex)然后ghMutex这个是互斥对象的句柄.
然后在我要看结果按钮中,最后用完要记得,关闭这个互斥对象
CloseHandle(ghMutex);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
信号量来实现线程同步
上面几种不管是互斥锁,还是Critical Section,还是用原子锁,
都是一个线程,同时操作一个逻辑,这样来保护这个逻辑,不受多线程的影响,
这个信号量,允许,支持多个线程同一时间操作多个对象.
举个例子,
比如租车,我们有10台车,但是有50个人要租,那么应该是
有10个人可以同时租到车.也就是多个线程同一时间可以操作多个对象
另外前面咱们讲的互斥锁,还是Critical Section,还是用原子锁都是10台车,50个人要租,
但是能,同一时间,只能一个人去用一台车.
举个例子:
可以看到这里
CreateSemaphore这里有4个参数
第一个是LPSECURITY_ATTRIBUTES是安全属性,用不到可以填入NULL
第二个参数是lInitialCount
第三个参数是lMaximumCount
这两个的参数意思是,lMaximumCount这个相当于一共有多少资源,类似于上面的10台车,那么
lInitialCount是开始使用的时候,允许一次使用几台车,使用多少资源,一般
lInitialCount要小于等于lMaximumCount
然后
lpName这个是给这个信号量,起了个名字.
首先我们定义一个信号量
ghSemaphore
然后我们在创建线程按钮中创建信号量
CreateSemaphore(NULL,10,10,NULL)
这个第一个NULL 是线程安全属性传入NULL,
第二个是初始的可以使用的资源数量
第三个是总共有的资源数量
第4个是NULL是信号量的名字可以起一个,用不到可以传入NULL
然后它再创建50个线程,然后同时去操作,传入idx
然后再去看看这个线程函数,
这里就是不停的打印出,这个当前线程的id
然后打印完以后,用完了信号量,把信号量释放
ghSemaphore,注意这里
ReleaseSemaphore(ghSemaphore,1,NULL)
第一个参数是ghSemaphore这个是信号量,1这个是要释放多少个资源,这里是释放1个,然后最后一个,
以前的个数不用管,传入NULL
使用的时候开始要
调用
WairForSingleObject(ghSemaphore,0);来获取信号量
这里的0的作用,就是不等待,意思就是,比如原来有1个厕所,现在我们有10个厕所,那么就不用等待了,也没有
超时时间了.这里超时时间就设置为0.
并且获取信号量的结果
并且这里判断结果,是WAIT_OBJECT_0的时候
这里进行输出,然后ReleaseSemaphore(ghSemaphore,1,NULL);
如果是请求的时候,比如10个信号量用完了,那么就会产生等待,
WAIT_TIMEOUT的时候,就要进行等待的处理.
用完了以后,最后还要进行关闭句柄.
然后在这里
这里执行一下,点击创建线程,可以看到debugview中显示的可以看到也有wait timed out!的
这个Event的方式,如果是车的话,上面咱们说的,
互斥锁,信号量,共享变量,Critical Section可以认为是自动档的,因为每当
WaitForSingleObject被一个线程调用的时候,自动会变成无信号的,如果是信号量的话,
这个时候,别的线程调用的时候就没办法用了,而
这个Event事件是可以允许自己去设置的,
比如自己去设置当WaitForSingleObject被调用的时候,自己去设置这个信号,自己去setevent设置信号,以及释放信号.
看例子
这里如果是bManualReset这个变量如果是false的话就是自动设置,就是说,使用方法,跟上面说的信号量是一样的,
但是如果是true的话,那么就不是自动设置,也就说,需要自己去,调用WaitForSingleObject的时候,去把信号量
设置为无信号的,非激发状态.
然后用完以后再用SetEvent设置为激发状态,再释放信号.
lpName是事件的名称,第一个lpEentAttributes,是线程安全属性
这里第一个参数是NULL,第二个参数是TRUE表示,手动设置信号,
第三个参数是TRUE,表示手动设置的是激发态,也就是需要手动设置信号的释放.
这个事件的方式的多线程同步,没有举例子,具体的例子,到时候用的时候去查一下吧.通过事件进行线程间同步.
credreamer~夹狗狮 认证博客专家 推荐算法 算法 神经网络 从事10年编程工作,工作涉及到.Net,Java,C等编程语言,爱好领域,算法,人工智能,大数据等领域, 虚心求教,一起进步,credream 创梦 是大学期间想的个词,如今一晃10多年已过....