1.Linux的多线程和同步
1)多线程
http://blog.csdn.net/chencheng126/article/details/43916385
Linux是基于进程为单位组织操作,线程也是基于进程。
多线程就是允许在一个进程内存在多个控制权,以便多个函数处于激活状态,从而让多个函数同时运行。即使单CPU的计算机,也可以通过不停地在不同线程的指令切换,从而达到多线程同时运行的效果。
2)并发
多线程相当于一个并发系统。多个任务可以共享资源,特别是同时写入某个变量时,就需要解决同步的问题。
3)多线程的同步
i.互斥锁(mutex)
锁上(lock)和打开(unlock)两个状态。mutex_lock()和mutex_unlock()之间的操作,不会被其它线程影响,形成原子操作。形象的例子:一个人的洗手间。
II.条件变量
条件变量经常与互斥锁合作。它比较适用于多个线程等待某个条件发生的场景。在这种情况下,如果不使用条件变量,每个线程就要不断尝试获得互斥锁,这将大大消耗系统的资源。
举个例子:100个工人装修房子,每人负责装修一个房子。当10个房间装修好以后,老板通知这10个人喝啤酒。
III)读写锁
和互斥锁很类似。它的主要作用是,多线程可以同时读取资源,而具有危险性的写操作则得到了互斥锁的保护。
2.Linux多线程编程详细解析--条件变量
http://blog.csdn.net/chencheng126/article/details/43916355
1)常用的函数
pthread_cond_init,初始化条件变量
pthread_cond_wait,解锁mutex指向的互斥锁,线程阻塞在条件变量上。
pthread_cond_signal,解除在条件变量上的阻塞的某个线程
pthread_cond_timedwait,阻塞直到指定时间,即使条件未发生也会解除。
pthread_cond_broadcast,释放阻塞的所有线程。
pthread_cond_destroy,释放条件变量
2)例子
等待线程
1。使用pthread_cond_wait前要先加锁
2。pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活
3。pthread_cond_wait被激活后会再自动加锁
激活线程:
1。加锁(和等待线程用同一个锁)
2。pthread_cond_signal发送信号
3。解锁
激活线程的上面三个操作在运行时间上都在等待线程的pthread_cond_wait函数内部。
实用的几个例子,可以参见原文。
3.线程同步之条件变量使用手记
http://blog.csdn.net/chencheng126/article/details/43927607
这篇文章讨论的是,在IO接受到数据的时候,如何高效的通知逻辑线程(基于线程池)工作的问题。类似的例子:餐厅等位问题。领班接到客人后,如何高效的通知侍应生去接待客人。
对于条件变量的理解,为什么有了Mutex,还要再加条件变量。mutex是给资源加的互斥锁,保证对于每个线程,对于资源的操作时个原子操作。而条件变量,是用来阻塞线程。下文中的例子是为了解决假激活的问题,也就是线程被激活了,但是却没有什么活要干。
4.Linux线程开发API以及一些经验
http://blog.csdn.net/chencheng126/article/details/43951311
1.对linux多线程API有一个总结
2.linux多线程中的5条经验
介绍了其它开源类库进行多线程开发,比如boost,对跨平台支持不错,如果要求高稳定的跨平台开发,首选boost.
对象 | 操作 | Linux Pthread API | Windows SDK 库对应 API |
线程 | 创建 | pthread_create | CreateThread |
退出 | pthread_exit | ThreadExit | |
等待 | pthread_join | WaitForSingleObject | |
互斥锁 | 创建 | pthread_mutex_init | CreateMutex |
销毁 | pthread_mutex_destroy | CloseHandle | |
加锁 | pthread_mutex_lock | WaitForSingleObject | |
解锁 | pthread_mutex_unlock | ReleaseMutex | |
条件 | 创建 | pthread_cond_init | CreateEvent |
销毁 | pthread_cond_destroy | CloseHandle | |
触发 | pthread_cond_signal | SetEvent | |
广播 | pthread_cond_broadcast | SetEvent / ResetEvent | |
等待 | pthread_cond_wait / pthread_cond_timedwait | SingleObjectAndWait |
5.Linux线程池
为什么使用线程池?基本原理?一个简单的例子。
这篇文章说的简单清楚。
http://blog.csdn.net/chencheng126/article/details/43954775
-----------------------------------------------------------------------------------------------------------------------
一个的例子。参见http://blog.csdn.net/chencheng126/article/details/43916355
在linux下通过gcc编译,加上-lpthread
gcc -o pthread_cond2 pthread_cond2.c -lpthread
如果要用gdb调试,编译时需要加上-g参数:
gcc -g -Wall -o pthread_cond2 pthread_cond2.c -lpthread
运行:
./pthread_cond2
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t counter_lock;
pthread_cond_t counter_nonzero;
int counter = 0;
int estatus = -1;
void *decrement_counter(void *argv);
void *increment_counter(void *argv);
int main(int argc, char **argv)
{
printf("counter: %d\n", counter);
pthread_t thd1, thd2;
int ret;
ret = pthread_create(&thd1, NULL, decrement_counter, NULL);
if(ret){
perror("del:\n");
return 1;
}
ret = pthread_create(&thd2, NULL, increment_counter, NULL);
if(ret){
perror("inc: \n");
return 1;
}
int counter = 0;
while(counter != 10){
printf("counter(main): %d\n", counter);
sleep(1);
counter++;
}
return 0;
}
void *decrement_counter(void *argv)
{
printf("counter(decrement): %d\n", counter);
pthread_mutex_lock(&counter_lock);
while(counter == 0)
pthread_cond_wait(&counter_nonzero, &counter_lock);
printf("counter--(before): %d\n", counter);
counter--;
printf("counter--(after): %d\n", counter);
pthread_mutex_unlock(&counter_lock);
return &estatus;
}
void *increment_counter(void *argv)
{
printf("counter(increment): %d\n", counter);
pthread_mutex_lock(&counter_lock);
if(counter == 0)
pthread_cond_signal(&counter_nonzero);
printf("counter++(before): %d\n", counter);
counter++;
printf("counter++(after): %d\n", counter);
pthread_mutex_unlock(&counter_lock);
return &estatus;
}
运行结果:
counter: 0
counter(main): 0
counter(decrement): 0
counter(increment): 0
counter++(before): 0
counter++(after): 1
counter--(before): 1
counter--(after): 0
counter(main): 1
counter(main): 2
counter(main): 3
counter(main): 4
counter(main): 5
counter(main): 6
counter(main): 7
counter(main): 8
counter(main): 9