线程同步方式
Posted 仇实
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程同步方式相关的知识,希望对你有一定的参考价值。
11-1和11-2的具体区别?
portion -> 部分
什么是分离?
在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源(如栈)是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。
线程的分离状态决定一个线程以什么样的方式来终止自己。在上面的例子中,我们采用了线程的默认属性,即为非分离状态(即可结合的,joinable,需要回收),这种情况下,原有的线程等待创建的线程结束;只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。
总之为了在使用 pthread 时避免线程的资源在线程结束时不能得到正确释放,从而避免产生潜在的内存泄漏问题,在对待线程结束时,要确保该线程处于 detached 状态,否着就需要调用 pthread_join() 函数来对其进行资源回收。
静态分配和动态分配?
静态分配发生在程序编译和连接的时候。动态分配则发生在程序调入和执行的时候。
堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由函数malloc进行分配。不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实现。
互斥锁mutex
用于保证在任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒
互斥锁是用于线程的互斥的
自旋锁:spinlock
在任何时刻同样只能有一个线程访问对象。但是当获取锁操作失败时,不会进入睡眠,而是会在原地自旋,直到锁被释放。这样节省了线程从睡眠状态到被唤醒期间的消耗,
在加锁时间短暂的环境下会极大的提高效率。但如果加锁时间过长,则会非常浪费CPU资源
读写锁:rwlock
区分读和写,处于读操作时,可以允许多个线程同时获得读操作。但是同一时刻只能有一个线程可以获得写锁。其它获取写锁失败的线程都会进入睡眠状态,直到写锁释放时被唤醒。
注意:写锁会阻塞其它读写锁。当有一个线程获得写锁在写时,读锁也不能被其它线程获取;写优先于读,当有线程因为等待写锁而进入睡眠时,则后续读者也必须等待
适用于读取数据的频率远远大于写数据的频率的场合。
信号量:semaphore
是用于线程间同步的,当一个线程完成操作后就通过信号量通知其它线程,然后别的线程就可以继续进行某些操作了。
信号量是用于线程间同步,也就是调度线程的,
带有超时的读写锁
长时间没有拿到锁,返回ETIMEDOUT
条件变量
条件变量是利用线程间共享的全局变量进行同步的一种机制。
例如读者写者问题,读者在消息队列为空时,会利用pthread_cond_wait挂起,等待写者写入队列,并传送pthread_cond_signal,再被唤醒,进行读的工作。
参考UNIX环境高级编程图11-15
屏障
屏障(barrier)是用户协调多个线程并行工作的同步机制。屏障允许每个线程等待,直到所有的合作线程都达到某一点,然后从该点继续执行。
int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned count);
初始化屏障时,可以使用count参数指定,在允许所有线程继续运行之前,必须到达屏障的线程数目。
使用内存屏障,以强制该语句前后的指令以正确的次序完成
a++; b=f(a); c--;
上句不使用屏障时,可能会以下面的顺序执行。
a++; c--; b=f(a);
但是没有问题。
obj->data = xxx; obj->ready = 1;
当设置了data之后,记下标志,然后在另一个线程中可能执行:
if (obj->ready) do_something(obj->data);
如果标志被置位先于data被设置,那么结果是收到了do_something(未修改的obj->data)。
这时候就需要强制语句先后顺序.
pthread_barrier_init(barrier,NULL,2);
obj->data = xxx; obj->ready = 1;pthread_barrier_wait(*barrier);
pthread_barrier_wait(*barrier);if (obj->ready) do_something(obj->data);
https://blog.csdn.net/michael...
以上是关于线程同步方式的主要内容,如果未能解决你的问题,请参考以下文章