java 条件变量_Windows下条件变量的实现
條件變量是什么?
是一種同步對象。
條件變量有什么用?
用于復(fù)雜的、多線程的、多核的程序中,實(shí)現(xiàn)多個(gè)線程間同步任務(wù)。
條件變量與其它同步對象的區(qū)別?
與事件、互斥鎖、segment等同步對象相比,條件變量最大的不同在于”條件“二字,其它同步對象的同步”條件“是固定的,如事件的被激發(fā),互斥鎖被釋放,而條件變量的"條件"是完全自定義的,比如你可以實(shí)現(xiàn)當(dāng)”張三賺了5塊錢、李四在看電視、奧巴馬訪問馬爾它“時(shí),條件變量完成同步。所以說條件變量可用于復(fù)雜的同步任務(wù)。
Windows下有沒有條件變量?
簡單的答案是:沒有,Windows API沒有提供條件變量對象,這就是本文會存在的原因和要解決的問題。
復(fù)雜點(diǎn)的答案是:
使用Windows Vista之后的版本(Vista之后的版本提供了native的條件變量對象;
從開源庫中抽取;
你可以自已實(shí)現(xiàn);
方案1不現(xiàn)實(shí),因?yàn)楝F(xiàn)階段你的客戶大多數(shù)還是使用windows xp/2003以下的版本,而且Vista賣的也并不好;
方案2可以參考ace庫,不過太多條件宏和不相關(guān)代碼,難以抽取使用(你不可能為了一個(gè)同步變量,而扯進(jìn)整個(gè)龐大的ace庫吧);
方案3難度更大,必須要熟悉多線程編程,還要考慮很多變態(tài)的細(xì)節(jié);
我就是采用方案3 -- 自已實(shí)現(xiàn)的。因?yàn)榫W(wǎng)上沒有現(xiàn)成的,不得已而為之!而你就不必重新造輪子,直接copy下面的代碼到你的項(xiàng)目里就可以直接使用了(只要你的項(xiàng)目是C++的)。
實(shí)現(xiàn)代碼如下:
class my_mutex
{
public:
my_mutex (bool be_initial_owner = false)
{
mutex_ = CreateMutexA (NULL, be_initial_owner, NULL);
}
~my_mutex (void)
{
CloseHandle (mutex_);
}
public:
int acquire (void)
{
DWORD ret = WaitForSingleObject (mutex_, INFINITE);
return ret == WAIT_OBJECT_0 ? 0 : -1;
}
int release (void)
{
BOOL bret = ReleaseMutex (mutex_);
return bret ? 0 : -1;
}
HANDLE handle (void)
{
return mutex_;
}
protected:
HANDLE mutex_;
};
class my_semaphore
{
public:
my_semaphore (long init_count, long max_count = (std::numeric_limits::max)())
{
assert (init_count >= 0 && max_count > 0 && init_count <= max_count);
sema_ = CreateSemaphoreA (NULL, init_count, max_count, NULL);
}
~my_semaphore (void)
{
CloseHandle (sema_);
}
public:
int post (long count = 1)
{
BOOL bret = ReleaseSemaphore (sema_, count, NULL);
return bret ? 0 : -1;
}
int wait (long timeout = -1)
{
DWORD ret = WaitForSingleObject (sema_, timeout);
return ret == WAIT_OBJECT_0 ? 0 : -1;
}
HANDLE handle (void)
{
return sema_;
}
protected:
HANDLE sema_;
};
template
class my_condition
{
public:
my_condition (MUTEX &m)
: mutex_ (m), waiters_ (0), sema_ (0)
{}
~my_condition (void)
{}
public:
/// Returns a reference to the underlying mutex_;
MUTEX &mutex (void)
{
return mutex_;
}
/// Signal one waiting thread.
int signal (void)
{
// must hold the external mutex before enter
if ( waiters_ > 0 )
sema_.post ();
return 0;
}
/// Signal *all* waiting threads.
int broadcast (void)
{
// must hold the external mutex before enter
if ( waiters_ > 0 )
sema_.post (waiters_);
return 0;
}
int wait (unsigned long wait_time = -1)
{
// must hold the external mutex before enter
int ret = 0;
waiters_++;
ret = SignalObjectAndWait (mutex_.handle (), sema_.handle (), wait_time, FALSE);
mutex_.acquire ();
waiters_ --;
return ret == WAIT_OBJECT_0 ? 0 : -1;
}
protected:
MUTEX &mutex_;
/// Number of waiting threads.
long waiters_;
/// Queue up threads waiting for the condition to become signaled.
my_semaphore sema_;
};
使用條件變量的示例:
/// 公共部分
// my_mutx m;
// my_condition c (m);
/// 消費(fèi)者
m.acquire();
while (!condition_is_satisfied())
{
c.wait(300);
}
handle_something();
m.release();
/// 生產(chǎn)者
produce_something();
m.acquire();
c.signal();
m.release();
以上代碼采用模板實(shí)現(xiàn),變件變量類my_condition的模板參數(shù)是與條件變量配合使用的互斥量類型,為了方便直接使用,互斥量類型我也一并提供了: my_mutex。
代碼我已在項(xiàng)目中測試使用過,如果發(fā)現(xiàn)問題,歡迎各路高手批評指正。
2018.6.11新增:
根據(jù)MSDN文檔對SignalObjectAndWait函數(shù)的描述,本文描述的代碼存在死鎖的風(fēng)險(xiǎn):條件滿足的信號通知丟失。解決的方法就是在調(diào)用my_condition的wait方法時(shí),一定要加上比較短的超時(shí)參數(shù)(比如300毫秒或者幾秒,根據(jù)實(shí)際情況調(diào)整),循環(huán)檢測以重新發(fā)現(xiàn)條件已經(jīng)滿足了(條件不會丟失,保存在信號量里)。MSDN原文如下:
Note that the "signal" and "wait" are not guaranteed to be performed as an atomic operation. Threads executing on other processors can observe the signaled state of the first object before the thread calling SignalObjectAndWait begins its wait on the second object.
---------------------
作者:leafarmy
來源:CSDN
原文:https://blog.csdn.net/leafarmy/article/details/4039548
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的java 条件变量_Windows下条件变量的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java kafka 消费_java编程
- 下一篇: 诸神战纪2java_诸神战纪2死神归来