C++11
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <list>
using namespace std;
/* mutex(互斥量)
* ************************************************************************************************
* 互斥量 版本 作用
* mutex C++11 最基本的互斥量
* timed_mutex C++11 有超时机制的互斥量
* recursive_mutex C++11 可重入的互斥量
* recursive_timed_mutex C++11 结合timed_mutex和recursive_mutex特点的互斥量
* shared_timed_mutex C++14 具有超时机制的可共享互斥量
* shared_mutex C++17 共享的互斥量
* ************************************************************************************************
* API:#include <mutex>
* 1、加锁
* @ void lock();
* @ void try_lock();
* 2、解锁
* void unlock();
*
* ****************************************************************************
* 互斥量管理 版本 作用
* lock_guard C++11 基于作用域的互斥量管理
* unique_lock C++11 更加灵活的互斥量管理
* shared_lock C++14 共享互斥量的管理
* scope_lock C++17 多互斥量避免死锁的管理
* *****************************************************************************
*
* //!重复加锁,是一个错误的做法。所谓“行为未定义”即在不同平台上可能会有不同的行为。
* int main()
* {
* std::mutex mutex;
* mutex.lock();
* mutex.lock();
* mutex.unlock();
* return 0;
* }
*/
/*
int g_number = 0;
std::mutex g_mutex;
void worker_thread(int id)
{
for (int i = 0;i < 3; i++)
{
g_mutex.lock();
++g_number;
printf("id:%d,g_number:%d\n",id,g_number);
g_mutex.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main()
{
std::thread t1(worker_thread,0);
std::thread t2(worker_thread,10);
t1.join();
t2.join();
return 0;
}
*/
/* std::condition_variable(条件变量)
* API:#include <conditionvariabl>
* 1、
*/
class Task
{
public:
Task(int taskID)
{
m_taskID = taskID;
}
void doTask()
{
std::cout << "handle a task, taskID: " << m_taskID << ", threadID: " << std::this_thread::get_id() << std::endl;
}
private:
int m_taskID;
};
std::mutex g_mutex;
std::list<Task*> g_tasklist;
std::condition_variable g_cond;
void consumer_thread()
{
Task *pTask = NULL;
while (true)
{
std::unique_lock<std::mutex> guard(g_mutex);
while (g_tasklist.empty())
{
//如果获得了互斥锁,但是条件不合适的话,pthread_cond_wait 会释放锁,不往下执行
//当发生变化后,条件合适,pthread_cond_wait 将直接获得锁
g_cond.wait(guard);
}
pTask = g_tasklist.front();
g_tasklist.pop_front();
if (pTask == NULL)
continue;
pTask->doTask();
delete pTask;
pTask = nullptr;
}
}
void producer_thread()
{
int taskID = 0;
Task * pTask = NULL;
while (true) {
pTask = new Task(taskID);
//使用括号减小guard锁的作用范围
{
std::lock_guard<std::mutex> guard(g_mutex);
g_tasklist.push_back(pTask);
std::cout << "producer a task, taskID: " << taskID << ", threadID: " << std::this_thread::get_id() << std::endl;;
}
//释放信号量,通知消费者线程
g_cond.notify_one();
taskID++;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main()
{
//创建5个消费者线程
std::thread ct1(consumer_thread);
std::thread ct2(consumer_thread);
std::thread ct3(consumer_thread);
std::thread ct4(consumer_thread);
std::thread ct5(consumer_thread);
//创建1个生产者线程
std::thread pt(producer_thread);
pt.join();
ct1.join();
ct2.join();
ct3.join();
ct4.join();
ct5.join();
return 0;
}
Linux平台
#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
/* Mutex
* API: #include <pthread.h>
* 1.init mutex
* @ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
* @ int pthread_mutex_init(pthread_mutex_t* restrict mutex, const pthread_mutextattr_t *restrict attr);0:successfully
* 2.delete mutex
* int pthread_mutex_destroy(pthread_mutex_t *mutex);0:successfully
* 3.lock
* int pthread_mutex_lock(pthread_mutex_t *mutex);
* 4.trylock
* int pthread_mutex_trylock(pthread_mutex_t *mutex);
* 5.unlock
* int pthread_mutex_unlock(pthread_mutex_t *mutex);
* 6.init mutexattr
* int pthread_mutexattr_init(pthread_mutexattr_t* attr);
* 7.delete mutexattr
* int pthread_mutexattr_destroy(pthread_mutexattr_t* attr);
* 8.set mutexattr
* int pthread_mutexattr_settype(pthread_mutexattr_t* attr,int type);
* 9.get mutexattr
* int pthread_mutexattr_gettype(const pthread_mutexattr_t*restrict attr, int* restrict type);
*NOTE:
* 1.使用 PTHREAD_MUTEX_INITIALIZER 初始化的互斥量无须销毁;
* 2.不要去销毁一个已经加锁或正在被条件变量使用的互斥体对象
* 3.创建 mutex 对象后,再对其加锁,加锁后才对其进行解锁操作,解锁后才销毁
* 4.mutex 锁的类型(pthread_mutex_init 第二个参数)
*/
//! PTHREADMUTEXNORMAL(普通锁)
//个普通锁加锁以后,其他线程会阻塞在 pthread_mutex_lock 调用处, 直到对互斥体加锁的线程释放了锁
/*
pthread_mutex_t g_mutex;
int g_number = 0;
void * worker_thread(void * param)
{
pthread_t ThId = pthread_self();
while (1) {
pthread_mutex_lock(&g_mutex);
printf("ThId:%d\n",ThId);
g_number++;
printf("ThId:%d,value:%d\n",ThId,g_number);
pthread_mutex_unlock(&g_mutex);
sleep(1);
}
}
int main(int argc, char *argv[])
{
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_NORMAL);
pthread_mutex_init(&g_mutex,&mutex_attr);
pthread_t workthread[5];
for (int i = 0;i < 5; i++)
{
pthread_create(&workthread[i],NULL,worker_thread,NULL);
}
for (int i = 0;i < 5; i++)
{
pthread_join(workthread[i],NULL);
}
pthread_mutex_destroy(&g_mutex);
pthread_mutexattr_destroy(&mutex_attr);
return 0;
}
*/
/*
//一个线程如果对一个已经加锁的普通锁再次使用 pthread_mutex_lock 加锁,程序会阻塞在第二次调用 pthread_mutex_lock 代码处
//在这种类型的情况, pthread_mutex_trylock 函数如果拿不到锁,不会阻塞,函数会立即返回,并返回 EBUSY 错误码
int main(int argc, char *argv[])
{
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL);
int res = pthread_mutex_lock(&mutex);
printf("mutex lock,res = %d\n",res);
res = pthread_mutex_lock(&mutex);//对一个已经加锁的普通锁再次使用 pthread_mutex_lock 加锁,程序会阻塞在第二次调用 pthread_mutex_lock 代码处
//res = pthread_mutex_trylock(&mutex);//在这种类型的情况, pthread_mutex_trylock 函数如果拿不到锁,不会阻塞,函数会立即返回,并返回 EBUSY 错误码
printf("mutex lock,res = %d\n",res);
pthread_mutex_destroy(&mutex);
return 0;
}
*/
//! PTHREADMUTEXERRORCHECK(检错锁)
//如果一个线程使用 pthread_mutex_lock 对已经加锁的互斥体对象再次加锁,pthread_mutex_lock 会返回 EDEADLK
/*
int main()
{
pthread_mutex_t mutex;
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex,&mutex_attr);
int res = pthread_mutex_lock(&mutex);
printf("res = %d\n",res);
res = pthread_mutex_lock(&mutex);
printf("res = %d\n",res);
if (res == EDEADLK)
{
printf("EDEADLK\n");
}
pthread_mutex_destroy(&mutex);
pthread_mutexattr_destroy(&mutex_attr);
return 0;
}
*/
//当前线程重复调用 pthread_mutex_lock 会直接返回 EDEADLOCK,其他线程如果对这个互斥体再次调用 pthread_mutex_lock 会阻塞在该函数的调用处
/*
pthread_mutex_t g_mutex;
void *work_thread(void *param)
{
pthread_t ThId = pthread_self();
while (1)
{
int res = pthread_mutex_lock(&g_mutex);
if (res == EDEADLK)
{
printf("ThId:%d,res:EDEADLK\n");
}
else
{
printf("ThID:%d,res:%d\n",res);
}
//pthread_mutex_unlock(&g_mutex);
sleep(1);
}
}
int main()
{
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&g_mutex,&mutex_attr);
pthread_mutex_lock(&g_mutex);
pthread_t workthread[5];
for (int i = 0;i < 5; i++)
{
pthread_create(&workthread[i],0,work_thread,NULL);
}
for (int i = 0;i < 5; i++)
{
pthread_join(workthread[i],NULL);
}
pthread_mutex_destroy(&g_mutex);
pthread_mutexattr_destroy(&mutex_attr);
return 0;
}
*/
//! PTHREAD_MUTEX_RECURSIVE(嵌套锁)
//该属性允许同一个线程对其持有的互斥体重复加锁,每次成功调
//用 pthread_mutex_lock 一次,该互斥体对象的锁引用计数就会增加一
//次,相反,每次成功调用 pthread_mutex_unlock 一次,锁引用计数就会
//减少一次,当锁引用计数值为 0 时允许其他线程获得该锁,否则其他线
//程调用 pthread_mutex_lock 时尝试获取锁时,会阻塞在那里
/* Semaphore(信号量)
* API:#include <semaphore.h>
* 1.init semaphore(信号量对象,信号量是否可以被初始化该信号量的进程 fork 出来的子进程共享,取值为0(不可以共享);1(可以共享),初始状态下资源的数量)
* int sem_init(sem_t *sem, int pshared, unsigned int value);
* 2.销毁一个信号量
* int sem_destroy(sem_t *sem);
* 3.资源计数递增 1,并解锁该信号量对,这样其他由于使用 sem_wait 被阻塞的线程会被唤醒
* int sem_post(sem_t *sem);
* 4.如果当前信号量资源计数为 0,函数 sem_wait 会阻塞调用线程;直到信号量对象的资源计数大于 0 时被唤醒,唤醒后将资源计数递减 1,然后立即返回
* int sem_wait(sem_t *sem);
* 5.函数 sem_trywait 是函数 sem_wait 的非阻塞版本,如果当前信号量对象的资源计数等于 0,sem_trywait 会立即返回不会阻塞调用线程,返回值是 ﹣1,错误码 errno 被设置成 EAGAIN
* int sem_trywait(sem_t *sem);
* 6.函数 sem_timedwait 是带有等待时间的版本,等待时间在第二个参数 abs_timeout 中设置,结构体的定义如下:
* strcut timespec
* {
* time_t tv_sec;
* long tv_nsec;
* }
* sem_timedwait 在参数 abs_timeout 设置的时间内等待信号量对象的资源计数大于 0,否则超时返回,返回值为 ﹣1,错误码 errno 是 ETIMEDOUT。
* 当使用 sem_timedwait 时,参数 abs_timeout 不能设置为 NULL,否则程序会在运行时调用 sem_timedwait 产生崩溃。
* int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
* NOTE:
* sem_wait、sem_trywait、sem_timedwait 函数将资源计数递减一时会同时锁定信号量对象,因此当资源计数为 1 时,
* 如果有多个线程调用sem_wait 等函数等待该信号量时,只会有一个线程被唤醒。
* 当sem_wait 函数返回时,会释放对该信号量的锁。
sem_wait、sem_trywait、sem_timedwait 函数调用成功后返回值均为0,调用失败返回 ﹣1,可以通过错误码 errno 获得失败原因。
sem_wait、sem_trywait、sem_timedwait 可以被 Linux 信号中断,被信号中断后,函数立即返回,返回值是 ﹣1,错误码 errno 为 EINTR。
虽然上述函数没有以 pthread_ 作为前缀,实际使用这个系列的函数时需要链接 pthread 库
*/
/*
#include <semaphore.h>
#include <list>
class Task
{
public:
Task(int taskId)
{
m_taskId = taskId;
}
void doTaks()
{
printf("consumer taskId:%d,threadId:%d\n",m_taskId,pthread_self());
}
private:
int m_taskId;
};
pthread_mutex_t g_mutex;
std::list<Task*> g_tasklist;
sem_t g_sem;
void *consumer_thread(void *param)
{
Task *pTask = NULL;
while (1)
{
if (0 != sem_wait(&g_sem))
continue;
if (g_tasklist.empty())
continue;
pthread_mutex_lock(&g_mutex);
pTask = g_tasklist.front();
g_tasklist.pop_front();
pthread_mutex_unlock(&g_mutex);
pTask->doTaks();
delete pTask;
pTask = nullptr;
}
}
void *producer_thread(void *param)
{
int taskId = 0;
Task *pTask = NULL;
while (1)
{
pTask = new Task(taskId);
pthread_mutex_lock(&g_mutex);
g_tasklist.emplace_back(pTask);
printf("producer taskId:%d,threadId:%d\n",taskId,pthread_self());
pthread_mutex_unlock(&g_mutex);
sem_post(&g_sem);
taskId++;
sleep(1);
}
}
int main()
{
pthread_mutex_init(&g_mutex,NULL);
sem_init(&g_sem,0,0);
pthread_t consumerthread[5];
pthread_t producerthread;
for (int i = 0; i < 5; i++)
{
pthread_create(&consumerthread[i],NULL,consumer_thread,NULL);
}
pthread_create(&producerthread,NULL,producer_thread,NULL);
for (int i = 0; i < 5; i++)
{
pthread_join(consumerthread[i],NULL);
}
pthread_join(producerthread,NULL);
pthread_mutex_destroy(&g_mutex);
sem_destroy(&g_sem);
return 0;
}
*/
/* cond(条件变量)
* API:#include <semaphore.h>
* 1.初始化条件变量
* @ pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
* @ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
* 2.销毁条件变量
* int pthread_cond_destroy(pthread_cond_t * cond);
* 3.等待条件变量的满足,如果条件变量代表的条件不满足,调用 pthread_cond_wait 的线程会一直等待下去
* int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t * restrict mutex);
* 4.pthread_cond_wait 非阻塞版本,它会在指定时间内等待条件满足,超过参数 abstime 设置的时候后 pthread_cond_timedwait 函数会立即返回
* int pthread_cond_timedwait(pthread_cond_t* restrict cond,pthread_mutex_t * restrict mutex, const struct timespec* restrict abstime);
* 5.唤醒因调用 pthread_cond_wait 等待的线程,一次随机唤醒一个线程
* int pthread_cond_signal(pthread_cond_t * cond);
* 6.唤醒因调用 pthread_cond_wait 等待的线程,可以同时唤醒多个线程
*/
/*
#include <list>
#include <semaphore.h>
class Task
{
public:
Task(int taskId)
{
m_taskId = taskId;
}
void doTaks()
{
printf("handle , taskId:%d,threadId:%d\n",m_taskId,pthread_self());
}
private:
int m_taskId;
};
pthread_mutex_t g_mutex;
std::list<Task*> g_tasklist;
pthread_cond_t g_cond;
void * consumer_thread(void *param)
{
Task * pTask = NULL;
while (1)
{
pthread_mutex_lock(&g_mutex);
while (g_tasklist.empty())
{
//如果获得了互斥锁,但是条件不合适的话,pthread_cond_wait 会释放锁,不往下执行
//当发生变化后,条件合适, pthread_cond_wait 将直接获得锁
//当 pthread_cond_wait 函数阻塞时,它会释放其绑定的互斥体,并阻塞线程,因此在调用该函数前应该对互斥体有个加锁操作
pthread_cond_wait(&g_cond,&g_mutex);
//当收到条件信号时, pthread_cond_wait 会返回并对其绑定的互斥体进行加锁,因此在其下面一定有个对互斥体进行解锁的操作
}
pTask = g_tasklist.front();
g_tasklist.pop_front();
pthread_mutex_unlock(&g_mutex);
if (pTask == NULL)
continue;
pTask->doTaks();;
delete pTask;
pTask = NULL;
}
}
void *producer_thread(void* param)
{
int taskID = 0;
Task * pTask = NULL;
while (1)
{
pTask = new Task(taskID);
pthread_mutex_lock(&g_mutex);
g_tasklist.emplace_back(pTask);
printf("producer,taskID:%d,threadID:%d\n",taskID,pthread_self());
pthread_mutex_unlock(&g_mutex);
//释放信号量,通知消费者线程
pthread_cond_signal(&g_cond);
taskID++;
sleep(1);
}
}
int main()
{
pthread_mutex_init(&g_mutex,NULL);
pthread_cond_init(&g_cond,NULL);
pthread_t consumerthread[5];
for (int i = 0;i < 5;i++)
{
pthread_create(&consumerthread[i],NULL,consumer_thread,NULL);
}
pthread_t producerthread;
sleep(1);
pthread_create(&producerthread,NULL,producer_thread,NULL);
pthread_join(producerthread,NULL);
for (int i = 0;i < 5; i++)
{
pthread_join(consumerthread[i],NULL);
}
pthread_mutex_destroy(&g_mutex);
pthread_cond_destroy(&g_cond);
return 0;
}
*/
/* rwlock(读写锁)
* API: #include <pthread.h>
* 1.初始化读写锁
* @ pthread_rwlock_t myrwlock = PTHREAD_RWLOCK_INITIALIZER;
* @ int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
* 2.销毁读写锁
* int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
* 3.请求读锁的系统 API 接口
* @ int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
* @ int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
* @ int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *abstime);
* 4.请求写锁的系统 API 接口
* @ int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
* @ int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
* @ int pthread_rwlock_timedwrlock(pthread_rwlock_t * abstime);
* 5.锁的释放
* int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
* 6.初始化读写锁的属性
* int pthread_rwlockattr_init(pthread_rwlockattr_t * attr);
* 7.销毁读写锁的属性
* int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
* 7.设置读写锁的属性
* int pthread_rwlockattr_setkid_np(pthread_rwlockattr_t * attr, int pref);
* 8.查询读写锁的属性
* int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref);
* pref 即设置读写锁的类型: enum
* {
* //读者优先(即同时请求读锁和写锁时,请求读锁的线程优先获得锁)
PTHREAD_RWLOCK_PREFER_READER_NP,
//不要被名字所迷惑,也是读者优先
PTHREAD_RWLOCK_PREFER_WRITER_NP,
//写者优先(即同时请求读锁和写锁时,请求写锁的线程优先获得锁)
PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP
* }
*NOTE:
* 1.读锁用于共享模式
* @ 如果当前读写锁已经被某线程以读模式占有了,其他线程调用 pthread_rwlock_rdlock (请求读锁)会立刻获得读锁;
* @ 如果当前读写锁已经被某线程以读模式占有了,其他线程调用 pthread_rwlock_wrlock (请求写锁)会陷入阻
* 2.写锁用的是独占模
* @ 如果当前读写锁被某线程以写模式占有,无论调用 pthread_rwlock_rdlock 还是 pthread_rwlock_wrlock 都会陷入阻塞,
* 即写模式下不允许任何读锁请求通过,也不允许任何写锁请求通过,读锁请求和写锁请求都要陷入阻塞,直到线程释放写
*
* *****************************************************************
* * 锁当前状态/其他线程请求锁类型 请求读锁 请求写锁 *
* *****************************************************************
* * 无锁 通过 通过 *
* *****************************************************************
* * 已经获得读锁 通过 阻止 *
* *****************************************************************
* * 已经获得写锁 阻止 阻止 *
* *****************************************************************
*
*/
int g_number = 0;
pthread_rwlock_t g_rwlock;
void *read_thread(void *param)
{
while (1)
{
//请求读锁
pthread_rwlock_rdlock(&g_rwlock);
printf("read thread ID:%d,g_number:%d\n",pthread_self(),g_number);
pthread_rwlock_unlock(&g_rwlock);
sleep(1);
}
}
void *write_thread(void *param)
{
while(1)
{
//请求写锁
pthread_rwlock_wrlock(&g_rwlock);
++g_number;
printf("write thread ID:%d,g_number:%d\n",pthread_self(),g_number);
pthread_rwlock_unlock(&g_rwlock);
sleep(1);
}
}
int main()
{
//!默认属性,其行为是请求读锁的线程优先获得到锁
//pthread_rwlock_init(&g_rwlock,NULL);
//!锁对象的属性修改成请求写锁优先
pthread_rwlockattr_t rwlockattr;
pthread_rwlockattr_init(&rwlockattr);
pthread_rwlockattr_setkind_np(&rwlockattr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
pthread_rwlock_init(&g_rwlock,&rwlockattr);
pthread_t readthread[5];
for (int i = 0;i < 5; i++)
{
pthread_create(&readthread[i],NULL,read_thread,NULL);
}
pthread_t writethread;
pthread_create(&writethread,NULL,write_thread,NULL);
for (int i = 0; i < 5; i++)
{
pthread_join(readthread[i],NULL);
}
pthread_join(writethread,NULL);
pthread_rwlock_destroy(&g_rwlock);
pthread_rwlockattr_destroy(&rwlockattr);
return 0;
}
Windows平台
#include <iostream>
#include <windows.h>
#include <string>
/* 临界区(关键段)
* CriticalSection
* 临界区内的代码同一时刻只允许一个线程去执行
* AIP:
* 1、初始化临界区
* void InitializaCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
* 2、删除临界区
* void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
* 3、尝试进入临界区
* bool TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
* 4、进入临界区
* void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
* 5、离开临界区
* void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
* 6、初始化创建带有自旋计数的临界区
* bool InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
*/
//利用RAII封装的临界区对象自解机制
class CSObject
{
CSObject(CRITICAL_SECTION &lpCriticalSection):CS(lpCriticalSection)
{
EnterCriticalSection(&CS);
}
~CSObject()
{
LeaveCriticalSection(&CS);
}
CRITICAL_SECTION &CS;
};
CRITICAL_SECTION CS;
int g_number;
unsigned int __stdcall WorkerThreadProc(LPVOID lpThreadParameter)
{
DWORD dwThreadID = ::GetCurrentThreadId();
while(true)
{
EnterCriticalSection(&CS);
std::cout << "EnterCriticalSection, ThreadID: "<< dwThreadID << std::endl;
g_number++;
std::cout << "EnterCriticalSection, ThreadID: "<< dwThreadID << ",Value: " << g_number << std::endl;
LeaveCriticalSection(&CS);
Sleep(1000);
}
}
int main()
{
InitializeCriticalSection(&CS);
HANDLE hWorkerThread1 = (HANDLE)_beginthreadex(NULL,0,WorkerThreadProc,NULL,0,NULL);
HANDLE hWorkerThread2 = (HANDLE)_beginthreadex(NULL,0,WorkerThreadProc,NULL,0,NULL);
WaitForSingleObject(hWorkerThread1,INFINITE);
WaitForSingleObject(hWorkerThread2,INFINITE);
CloseHandle(hWorkerThread1);
CloseHandle(hWorkerThread2);
DeleteCriticalSection(&CS);
return 0;
}
/* 事件
* Event
* API:
* 1、创建Event(安全属性、对象受信时行为(true:需要手动调用RsetEvent重置事件状态;false:自动重置事件状态)、初始状态是否受信(true:有信号;false:无信号)、事件名称)
* HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, bool bManualReset, bool bInitialState, LPCTSTR lpName);
* 2、设置受信
* bool SetEvent(HANDLE hEvent);
* 3重置事件句柄
* bool ResetEvent(HANDLE hEvent);
*/
//!1
bool g_bTaskCompleted = false;
std::string g_TaskResult;
HANDLE g_hTaskEvent = NULL;
unsigned int __stdcall WorkerThreadProc(LPVOID lpThreadParameter)
{
Sleep(3000);
g_TaskResult = "task completed";
g_bTaskCompleted = true;
SetEvent(g_hTaskEvent);
return 0;
}
int main()
{
g_hTaskEvent = CreateEvent(NULL,true,false,NULL);
HANDLE WorkerThread = (HANDLE)_beginthreadex(NULL,0,WorkerThreadProc,NULL,0,NULL);
DWORD dwResult = WaitForSingleObject(g_hTaskEvent,INFINITE);
if (dwResult == WAIT_OBJECT_0)
{
std::cout << g_TaskResult << std::endl;
}
CloseHandle(WorkerThread);
CloseHandle(g_hTaskEvent);
return 0;
}
*/
//!2
HANDLE g_event;
int g_number = 0;
unsigned int WINAPI WorkerThreadProcSub(LPVOID lpThreadParameter)
{
DWORD ThId = ::GetCurrentThreadId();
for (int i = 0;i < 100; i++)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(g_event,INFINITE))
{
printf("id:%d\n",(int)ThId);
//ResetEvent(g_event);
g_number--;
SetEvent(g_event);
printf("id:%d,-v=%d\n",(int)ThId,g_number);
}
}
return 0;
}
unsigned int WINAPI WorkerThreadProcAdd(LPVOID lpThreadParameter)
{
DWORD ThId = ::GetCurrentThreadId();
for (int i = 0;i < 100; i++)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(g_event,INFINITE))
{
printf("id:%d\n",(int)ThId);
//ResetEvent(g_event);
g_number++;
SetEvent(g_event);
printf("id:%d,+v=%d\n",(int)ThId,g_number);
}
}
return 0;
}
int main()
{
g_event = CreateEvent(NULL,false,true,NULL);
HANDLE Th1 = (HANDLE)_beginthreadex(NULL,0,WorkerThreadProcAdd,NULL,0,NULL);
HANDLE Th2 = (HANDLE)_beginthreadex(NULL,0,WorkerThreadProcSub,NULL,0,NULL);
WaitForSingleObject(Th1,INFINITE);
WaitForSingleObject(Th2,INFINITE);
CloseHandle(Th1);
CloseHandle(Th2);
CloseHandle(g_event);
return 0;
}
/* Mutex(互斥量)
* API:
* 1、创建互斥量(安全属性一般为NULL、设置调用CreateMutex是否立即拥有Mutex(true:拥有;false:不拥有)、对象名称)
* HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, bool bInitialOwner, LPCTSTR lpName);
* 2、释放互斥量
* bool ReleaseMutex(HANDLE hMutex);
*/
HANDLE g_Mutex = NULL;
int g_number = 0;
unsigned int WINAPI WorkerThreadProc(LPVOID plThreadParameter)
{
DWORD ThId = GetCurrentThreadId();
while (true) {
if (WAIT_OBJECT_0 == WaitForSingleObject(g_Mutex,1000))
{
g_number++;
printf("ThId:%d,value=%d\n",ThId,g_number);
ReleaseMutex(g_Mutex);
}
Sleep(1000);
}
return 0;
}
int main()
{
g_Mutex = CreateMutex(NULL,false,NULL);
HANDLE hWorkerThread[5];
for (int i = 0; i < 5; i++)
{
hWorkerThread[i] = (HANDLE)_beginthreadex(NULL,0,WorkerThreadProc,NULL,0,NULL);
}
WaitForMultipleObjects(5,hWorkerThread,true,INFINITE);
for (int i = 0;i < 5; i++)
{
CloseHandle(hWorkerThread[i]);
}
CloseHandle(g_Mutex);
return 0;
}
/* Semaphore(信号量)
* API:
* 1、创建信号量(安全属性NULL、资源数量、最大资源数量、对象名称)
* HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, LPCTSTR lpName);
* 2、释放信号量(信号量句柄、需要增加的资源数量、函数执行成功后返回上一次资源的数量,若用不到可传入NULL)
* bool ReleaseSemaphore(HANDLE hSemaphore, long lReleaseCount, LPLONG lpPreviousCount);
*/
#include <time.h>
#include <list>
HANDLE g_Semaphore = NULL;
std::list<std::string> g_listChatMsg;
CRITICAL_SECTION g_CS;//保护消息的临界区对象
unsigned int WINAPI netWorkThread(LPVOID param)
{
//srand(time(0));
int nMsgIndex = 0;
while (true)
{
EnterCriticalSection(&g_CS);
int count = rand() % 4 + 1;
for (int i = 0; i < count; i++)
{
nMsgIndex++;
SYSTEMTIME st;
GetLocalTime(&st);
char szChatMsg[64] = {};
sprintf_s(szChatMsg,64,"[%04d-%02d-%02d %02d:%02d:%02d:%03d] A new msg, NO.%d.",
st.wYear,
st.wMonth,
st.wDay,
st.wHour,
st.wMinute,
st.wSecond,
st.wMilliseconds,
nMsgIndex);
g_listChatMsg.emplace_back(szChatMsg);
}
LeaveCriticalSection(&g_CS);
ReleaseSemaphore(g_Semaphore,count,NULL);
Sleep(1000);
}
return 0;
}
unsigned int WINAPI workerThread(LPVOID param)
{
DWORD ThId = GetCurrentProcessId();
std::string current;
while (true)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(g_Semaphore,INFINITE))
{
EnterCriticalSection(&g_CS);
if (!g_listChatMsg.empty())
{
current = g_listChatMsg.front();
g_listChatMsg.pop_front();
printf("ThId:%d, msg:%s\n",ThId, current.c_str());
}
LeaveCriticalSection(&g_CS);
}
}
return 0;
}
int main()
{
srand(time(0));
InitializeCriticalSection(&g_CS);
g_Semaphore = CreateSemaphore(NULL,0,4,NULL);
HANDLE netThread = (HANDLE)_beginthreadex(NULL,0,netWorkThread,NULL,0,NULL);
HANDLE workThread[4];
for (int i = 0; i < 4; i++)
{
workThread[i] = (HANDLE)_beginthreadex(NULL,0,workerThread,NULL,0,NULL);
}
WaitForMultipleObjects(4,workThread,true,INFINITE);
WaitForSingleObject(netThread,INFINITE);
for (int i = 0;i < 4; i++)
{
CloseHandle(workThread[i]);
}
CloseHandle(netThread);
CloseHandle(g_Semaphore);
DeleteCriticalSection(&g_CS);
return 0;
}