pthread用法

线程的一生始终处于下面四种状态之一:

我们每个人都并行地活在这个世界上 ,每一天每个人都干着不同的事情。每个人的人生都是不同的,从出生 -> 活着 -> 死去, 个中滋味,只能自己体味了。我们的线程兄弟也一样,只不过它的环境没有人类社会这么复杂,它的一生,被操作系统控制,被我们程序员控制着!呵呵,想想都觉 得这兄弟可怜啊!不过这哥们可不许小瞧了,功能大了去了!具体线程的定义和好处参考其它关于线程的资料。该篇主要讲线程兄弟的大体的一生(从被创建到销 毁)。进入正题:
线程的一生始终处于下面四种状态之一:
State Meaning
Ready 就绪状态,等待处理器的调度。可能是刚新创建的,或阻塞状态,等待的资源得到满足刚解除阻塞状态,或处于运行状态被别的线程抢占了处理器。
Running 运行状态,线程正在处理器上运行。多处理器可能会不止一个线程正在运行。
Blocked 阻塞状态,线程等待某些资源,不能运行。如:等待一个条件变量,锁定互斥量,或者等待I/O操作的完成。
Terminated 终止状态,线程从它的开始函数(创建时指定的)终止。调用pthread_exit或者被其它线程取消(cancelled)。此时,线程并没有被分离 (detached),也没有被连接(joined)。一旦线程被joined或detached, 将会被系统回收。


线程的状态图:线程状态图



1. 创建和使用线程常见的pthread函数
pthread_t thread;
int pthread_equal(pthread_t t1, pthread_t t2);
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start)(void*), void* arg);
pthread_t pthread_self();
int sched_yield();
int pthread_exit(void* value_ptr);
int pthread_detach(pthread_t thread);
int pthread_join(pthread_t thread, void** value_ptr);
2. 创建线程:
有一个比较特殊的线程, 就是主线程或者称为初始线程,它是当一个进程被创建时创建的。而其他线程则是在初始线程中调用pthread_create创建的。创建的新线程初始为Ready状态,等待处理器调度。
3. 执行线程:
线程被创建后,就会执行phtread_create的start参数指定的函数,我们可以通过pthread_create的arg参数向线程开始函数传递一个参数,若不想传就直接赋值NULL。
上 面提到了一个特殊的线程:初始线程,它的开始函数就是我们学习C/C++见到的第一个函数main,只不过这个开始函数不是由我们来调用的,而是由操作系 统Shell。操作系统先初始化进程,然后运行主线程的开始函数main。注意:初始线程和我们自己创建的线程有稍许不同:-开始函数参数不同,main 的参数是int arg, char* argv,而我们自己的线程参数是void* arg。-自己创建的线程开始函数返回了,其它线程可以继续执行。而初始线程开始函数main返回后进程会终止,导致其它正在运行的线程也就被强行终止, 若不想在main退出后关闭进程,可以在main最后调用pthread_exit,不过此时该进程就成了僵尸进程(defunct),直到所有线程执行 完毕。- 还有一个很重要的区别,多数系统上,初始线程使用的是进程的栈,而自己创建的线程则使用自己的栈,往往自建线程的栈没有初始线程的栈空间大,要注意线程栈 溢出哦!(phread提供了修改线程栈大小的函数,后面再说^_^)
4. 运行和阻塞
线程兄弟和我们一样,不能一直都醒着工作,它也要休息。线程一生大多处于三种状态:ready, running, 和blocked(和我一样,吃饭,工作,睡觉^_^)。 线程被创建时出于就绪状态,就绪状态等待处理器,处理器有空闲了,线程就转到运行状态疯狂工作,突然发现自己需要的其它资源(互斥量,条件变量)在别的线 程手里,或者别的线程优先级比自己大一下从它手里抢走了处理器,或处理器烦了它了(时间片已经用完),或自己不好意思不干事还占用处理器了(等待I/O操 作完成),就转换成阻塞状态,停止运行,可以休息下了。 休息可不是给它放长假,任务还没完成了...继续,当等待的资源得到满足,再次投入工作,进入运行状态。周而复始,直到任务完成。
5. 终止线程:
线程一般都是在开始函数执行完时终止的。线程开始函数中调用pthread_exit或者其它线程调用pthread_cancel都可以终止线程。终止后线程处于terminated状态(注意:不是destroyed),然后等待系统回收。

若创建线程时指定线程是detached的,直接在线程开始函数执行完后就会被回收。
若是joinable,那就需要初始线程或其他线程调用pthread_join来等待要终止的线程了, 同时还可以通过pthread_joind的第二个参数获得线程的返回值。pthread_join后,线程就被detached,然后被系统回收。
6. 回收线程
线程创建时,detachsate属性是PTHREAD_CREATE_DETACHED,则在开始函数返回后被回收。
或其他线程使用了pthread_join 或自己调用了pthread_detach,线程出于terminated状态后,立马就会被系统回收:释放系统资源和进程资源,包含线程返回值占用的内存,线程堆栈,寄存器状态等等。
转载  深入Phtread(二):线程的同步-Mutex 收藏

并 行的世界,没有同步,就失去了秩序,就会乱作一团!试想,交通没有红绿灯,生产线产品装配没有一定的顺序... 结果是显而易见的。多个线程也需要同步,否则程序运行起来结果不可预测,这是我们最不能容忍的。交通的同步机制就是红绿灯,Pthread提供了互斥量 (mutex)和条件变量(Condition Variables)两种机制去同步线程。
不变量,临界区和判定条件
互斥量(Mutex)
创建和销毁互斥量
锁定和解锁
调整mutex大小
使用多个mutex
锁定链
不变量,临界区和判定条件
不变量(Invariant):程序所做的一些假设,特别是指变量之间的关系。如:一个queue,有头节点,和其它数据节点,这些元素之间的连接关系就是不变量。当程序里面不变量遭受破坏时,后果往往是很严重的,轻则数据出错,重则程序直接崩溃。

临界区(Critical Section):处理共享数据的一段代码。

判定条件(Predicates):描述不变量状态的逻辑表达式。


互斥量(Mutex)
一般,多个线程之间都会共享一些数据,当多个线程同时访问操作这些共享数据时。问题出来了,一个线程正在修改数据时,另外一个可能也去操作这些数据,结果就会变得不一致了。如(gv=0是共享的数据):

线程A:a = gv; gv = a + 10;
线程B: b = gv; gv = a + 100;

可能发生A执行完a=gv(0)时,B开始执行b=gv(0); gv=a+100,此时gv=100,然后a执行gv=a+10,最后gv=10。并不是我们要的结果,我们的想法是两个线程并发的给gv加上一个值,期 望结果110。^_^ 若这是你银行卡的余额,若没有同步,那就惨了(你往卡里打钱,你有个朋友也同时往你卡里汇钱,很有可能余额只仅加上一方打的)。

互斥量就是为了解决这种问题而设计的,它是Dijkstra信号量的一种特殊形式。它使得线程可以互斥地访问共享数据。如:

    上图展示了三个线程共享一个互斥量,位于矩形中心线下方的线程锁定了该互斥量;位于中心线上方且在矩形范围内的线程等待该互斥量被解锁,出于阻塞状态,在 矩形外面的线程正常运行。刚开始,mutex是解锁的,线程1成功将其锁定,据为己有,因为并没有其它线程拥有它。然后,线程2尝试去锁定,发现被线程1 占用,所以阻塞于此,等到线程1解锁了该mutex,线程2立马将mutex锁定。过了会,线程3尝试去锁定mutex,由于mutex被锁定,所以阻塞 于此。线程1调用pthread_mutex_trylock尝试去锁定个mutex,发现该mutex被锁定,自己返回继续执行,并没有阻塞。继续线程 2解锁,线程3锁定成功,最后线程3完成任务解锁mutex。


创建和销毁互斥量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr);
int pthread_mutex_destroy(pthread_mutex_t* mutex);

不要尝试去使用复制的的mutex,结果未定义。

静态创建,当mutex以extern或者static存储时,可以用PTHREAD_MUTEX_INITIALIZER初始化,此时该mutex使用默认属性。
+ expand sourceview plaincopy to clipboardprint?
#include "error.h" 
#include <pthread.h> 

typedef struct my_struct_tag 

pthread_mutex_t mutex; 
int value; 
} my_struct_t; 

my_struct_t data = { PTHREAD_MUTEX_INITIALIZER, 0}; 

int main() 

return 0; 
}
#include "error.h"
#include <pthread.h>

typedef struct my_struct_tag
{
pthread_mutex_t mutex;
int value;
} my_struct_t;

my_struct_t data = { PTHREAD_MUTEX_INITIALIZER, 0};

int main()
{
return 0;
}

动态创建,往往使用mutex时,都会将它和共享数据绑在一起,此时就需要pthread_mutex_init去动态初始化了,记得用完后pthread_mutex_destroy。
+ expand sourceview plaincopy to clipboardprint?
#include "error.h" 
#include <pthread.h> 

typedef struct my_struct_tag 

pthread_mutex_t mutex; 
int value; 
} my_struct_t; 

int main() 

my_struct_t* data; 
int status; 

data = (my_struct_t*)malloc(sizeof(my_struct_t)); 
status = pthread_mutex_init(&data->mutex, NULL); 
if(status != 0) 
ERROR_ABORT(status, "pthread_mutex_init"); 

pthread_mutex_destroy(&data->mutex); 
free(data); 

return 0; 
}
#include "error.h"
#include <pthread.h>

typedef struct my_struct_tag
{
pthread_mutex_t mutex;
int value;
} my_struct_t;

int main()
{
my_struct_t* data;
int status;

data = (my_struct_t*)malloc(sizeof(my_struct_t));
status = pthread_mutex_init(&data->mutex, NULL);
if(status != 0)
ERROR_ABORT(status, "pthread_mutex_init");

pthread_mutex_destroy(&data->mutex);
free(data);

return 0;
}


锁定和解锁
原则见上面。
int pthread_mutex_lock(pthread_mutex_t* mutex);
int pthread_mutex_trylock(pthread_mutex_t* mutex);
int pthread_mutex_unlock(pthread_mutex_t* mutex);
+ expand sourceview plaincopy to clipboardprint?
#include <pthread.h> 
#include <sys/types.h> 
#include "error.h" 
#include <errno.h> 

#define SPIN 10000000 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
long counter; 
time_t end_time; 

void* counter_thread(void* arg) 

int status; 
int spin; 

while(time(NULL) < end_time) 

status = pthread_mutex_lock(&mutex); 
if(status != 0) 
ERROR_ABORT(status, "Lock mutex"); 

for(spin = 0; spin < SPIN; spin++) 
counter++; 

status = pthread_mutex_unlock(&mutex); 
if(status != 0) 
ERROR_ABORT(status, "Unlock mutex"); 
sleep(1); 


printf("Coutner is %#lx\n", counter); 

return NULL; 


void* monitor_thread(void* arg) 

int status; 
int misses = 0; 

while(time(NULL) < end_time) 

sleep(3); 

status = pthread_mutex_trylock(&mutex); 
if(status != EBUSY) 

if(status != 0) 
ERROR_ABORT(status, "Trylock mutex"); 

printf("Counter is %ld\n", counter/SPIN); 
status = pthread_mutex_unlock(&mutex); 
if(status != 0) 
ERROR_ABORT(status, "Unlock mutex"); 
}else
misses++; 

printf("Monitro thread missed update %d times.\n", misses); 
return NULL; 


int main() 

int status; 
pthread_t pid_counter; 
pthread_t pid_monitor; 

end_time = time(NULL) + 60; 

status = pthread_create(&pid_counter, NULL, counter_thread, NULL); 
if(status != 0) 
ERROR_ABORT(status, "fail to create thread counter"); 

status = pthread_create(&pid_monitor, NULL, monitor_thread, NULL); 
if(status != 0) 
ERROR_ABORT(status, "fail to create monitor thread"); 

status = pthread_join(pid_counter, NULL); 
if(status != 0 ) 
ERROR_ABORT(status, "fail to join counter thread"); 

status = pthread_join(pid_monitor, NULL); 
if(status != 0) 
ERROR_ABORT(status, "fail to join monitor thread"); 

return 0; 
}
#include <pthread.h>
#include <sys/types.h>
#include "error.h"
#include <errno.h>

#define SPIN 10000000

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
long counter;
time_t end_time;

void* counter_thread(void* arg)
{
int status;
int spin;

while(time(NULL) < end_time)
{
status = pthread_mutex_lock(&mutex);
if(status != 0)
ERROR_ABORT(status, "Lock mutex");

for(spin = 0; spin < SPIN; spin++)
counter++;

status = pthread_mutex_unlock(&mutex);
if(status != 0)
ERROR_ABORT(status, "Unlock mutex");
sleep(1);
}

printf("Coutner is %#lx\n", counter);

return NULL;
}

void* monitor_thread(void* arg)
{
int status;
int misses = 0;

while(time(NULL) < end_time)
{
sleep(3);

status = pthread_mutex_trylock(&mutex);
if(status != EBUSY)
{
if(status != 0)
ERROR_ABORT(status, "Trylock mutex");

printf("Counter is %ld\n", counter/SPIN);
status = pthread_mutex_unlock(&mutex);
if(status != 0)
ERROR_ABORT(status, "Unlock mutex");
}else
misses++;
}
printf("Monitro thread missed update %d times.\n", misses);
return NULL;
}

int main()
{
int status;
pthread_t pid_counter;
pthread_t pid_monitor;

end_time = time(NULL) + 60;

status = pthread_create(&pid_counter, NULL, counter_thread, NULL);
if(status != 0)
ERROR_ABORT(status, "fail to create thread counter");

status = pthread_create(&pid_monitor, NULL, monitor_thread, NULL);
if(status != 0)
ERROR_ABORT(status, "fail to create monitor thread");

status = pthread_join(pid_counter, NULL);
if(status != 0 )
ERROR_ABORT(status, "fail to join counter thread");

status = pthread_join(pid_monitor, NULL);
if(status != 0)
ERROR_ABORT(status, "fail to join monitor thread");

return 0;
}


调整mutex大小
mutex应该多大?这里的大小是相对的,如mutex锁定到解锁之间的代码只有一行,比起有10行的就小了。 原则是:尽可能大,但不要太大(As big as neccessary, but no bigger)。考虑下面的因素:1> mutex并不是免费的,是有开销的,不要太小了,太小了程序只忙于锁定和解锁了。2> mutex锁定的区域是线性执行的,若太大了,没有发挥出并发的优越性。
3> 自己掂量1和2,根据实际情况定,或者尝试着去做。
使用多个mutex
使用多个mutex一定要注意,防止死锁(deadlock)发生。下面是一个典型死锁:

线程A:pthread_mutex_lock(&mutex_a); pthread_mutex_lock(&mutex_b); ...
线程B:pthread_mutex_lock(&mutex_b); pthread_mutex_lock(&mutex_a); ...

存在这种可能,线程A执行了第一句,锁定了mutex_a;然后线程开始执行第一句锁定mutex_b;然后他们互相等待解锁mutex,A等mutex_b被解锁,B等mutex_a被解锁,不肯让步,出于死锁状态。
+ expand sourceview plaincopy to clipboardprint?
#include <pthread.h> 
#include "error.h" 
#include <time.h> 

pthread_mutex_t mutex_a = PTHREAD_MUTEX_INITIALIZER; 
pthread_mutex_t mutex_b = PTHREAD_MUTEX_INITIALIZER; 

void* thread1(void* arg) 

while(1) 

/*sleep(1);*/
pthread_mutex_lock(&mutex_a); 
pthread_mutex_lock(&mutex_b); 

printf("[%lu]thread 1 is running! \n", time(NULL)); 

pthread_mutex_unlock(&mutex_b); 
pthread_mutex_unlock(&mutex_a); 

return NULL; 


void* thread2(void* arg) 

while(1) 

/*sleep(1);*/

pthread_mutex_lock(&mutex_b); 
pthread_mutex_lock(&mutex_a); 

printf("[%lu]thread 2 is running! \n",time(NULL)); 

pthread_mutex_unlock(&mutex_a); 
pthread_mutex_unlock(&mutex_b); 


return NULL; 


int main() 

pthread_t tid1, tid2; 
int status; 

status = pthread_create(&tid1, NULL, thread1, NULL); 
if(status != 0) 
ERROR_ABORT(status, "thread 1"); 

status = pthread_create(&tid2, NULL, thread2, NULL); 
if(status !=0) 
ERROR_ABORT(status, "thread 2"); 

status = pthread_join(tid1, NULL); 
if(status != 0) 
ERROR_ABORT(status, "join thread1"); 

status = pthread_join(tid2, NULL); 
if(status != 0) 
ERROR_ABORT(status, "join thread2"); 
}
#include <pthread.h>
#include "error.h"
#include <time.h>

pthread_mutex_t mutex_a = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_b = PTHREAD_MUTEX_INITIALIZER;

void* thread1(void* arg)
{
while(1)
{
/*sleep(1);*/
pthread_mutex_lock(&mutex_a);
pthread_mutex_lock(&mutex_b);

printf("[%lu]thread 1 is running! \n", time(NULL));

pthread_mutex_unlock(&mutex_b);
pthread_mutex_unlock(&mutex_a);
}
return NULL;
}

void* thread2(void* arg)
{
while(1)
{
/*sleep(1);*/

pthread_mutex_lock(&mutex_b);
pthread_mutex_lock(&mutex_a);

printf("[%lu]thread 2 is running! \n",time(NULL));

pthread_mutex_unlock(&mutex_a);
pthread_mutex_unlock(&mutex_b);

}
return NULL;
}

int main()
{
pthread_t tid1, tid2;
int status;

status = pthread_create(&tid1, NULL, thread1, NULL);
if(status != 0)
ERROR_ABORT(status, "thread 1");

status = pthread_create(&tid2, NULL, thread2, NULL);
if(status !=0)
ERROR_ABORT(status, "thread 2");

status = pthread_join(tid1, NULL);
if(status != 0)
ERROR_ABORT(status, "join thread1");

status = pthread_join(tid2, NULL);
if(status != 0)
ERROR_ABORT(status, "join thread2");
}


解决死锁的方法:
固定锁定顺序(Fixed locking hierarchy):锁定mutex的顺序固定。
线程A:pthread_mutex_lock(&mutex_a); pthread_mutex_lock(&mutex_b); ...
线程B:pthread_mutex_lock(&mutex_a); pthread_mutex_lock(&mutex_b); ...

尝试和回退(Try and back off): 锁定第一个后,尝试锁定下一个,若锁定成功,继续尝试下一个,若锁定失败,解锁先去锁定的。

解锁顺序不会引起死锁.
+ expand sourceview plaincopy to clipboardprint?
#include <pthread.h> 
#include "error.h" 
#include <errno.h> 

#define ITERATIONS 100 


pthread_mutex_t mutex[3] = { 
PTHREAD_MUTEX_INITIALIZER, 
PTHREAD_MUTEX_INITIALIZER, 
PTHREAD_MUTEX_INITIALIZER 
}; 

int backoff = 1; 
int yield_flag = 0; 

void* lock_forward(void* arg) 

int i, iterate, backoffs; 
int status; 

for(iterate = 0; iterate < ITERATIONS; iterate++) 

backoffs = 0; 
for(i = 0; i < 3; i++){ 
if(i == 0) 

status = pthread_mutex_lock(&mutex[i]); 
if(status != 0) 
ERROR_ABORT(status,"Lock mutex"); 
}else

if(backoff) 
status = pthread_mutex_trylock(&mutex[i]); 
else
status = pthread_mutex_lock(&mutex[i]); 

if(status == EBUSY) 

backoff++; 
printf("forward locker backing off at %d.\n", i); 
for(; i >= 0; i--) 

status = pthread_mutex_unlock(&mutex[i]); 
if(status != 0) 
ERROR_ABORT(status, "Unlock mutex"); 

}else

if(status != 0) 
ERROR_ABORT(status, "Lock mutex"); 

printf("forward locker got %d \n", i); 



if(yield_flag){ 
if(yield_flag > 0) 
sched_yield(); 
else
sleep(1); 



printf("lock forward got all locks , %d backoffs\n", backoffs); 

pthread_mutex_unlock(&mutex[2]); 
pthread_mutex_unlock(&mutex[1]); 
pthread_mutex_unlock(&mutex[0]); 
sched_yield(); 


return NULL; 


void* lock_backward(void* arg) 

int i, iterate, backoffs; 
int status; 

for(iterate = 0; iterate < ITERATIONS; iterate++) 

backoffs = 0; 
for(i = 2; i >= 0; i--){ 
if(i == 2) 

status = pthread_mutex_lock(&mutex[i]); 
if(status != 0) 
ERROR_ABORT(status,"Lock mutex"); 
}else

if(backoff) 
status = pthread_mutex_trylock(&mutex[i]); 
else
status = pthread_mutex_lock(&mutex[i]); 

if(status == EBUSY) 

backoff++; 
printf("backward locker backing off at %d.\n", i); 
for(; i < 3; i++) 

status = pthread_mutex_unlock(&mutex[i]); 
if(status != 0) 
ERROR_ABORT(status, "Unlock mutex"); 

}else

if(status != 0) 
ERROR_ABORT(status, "Lock mutex"); 

printf("backward locker got %d \n", i); 



if(yield_flag){ 
if(yield_flag > 0) 
sched_yield(); 
else
sleep(1); 



printf("lock backward got all locks , %d backoffs\n", backoffs); 

pthread_mutex_unlock(&mutex[0]); 
pthread_mutex_unlock(&mutex[1]); 
pthread_mutex_unlock(&mutex[2]); 
sched_yield(); 



return NULL; 


int main(int argc, char* argv[]) 

pthread_t forward, backward; 
int status; 

if(argc > 1) 
backoff = atoi(argv[1]); 

if(argc > 2) 
yield_flag = atoi(argv[2]); 

status = pthread_create(&forward, NULL, lock_forward, NULL); 
if(status != 0) 
ERROR_ABORT(status, "Create forward"); 

status = pthread_create(&backward, NULL, lock_backward, NULL); 
if(status != 0) 
ERROR_ABORT(status, "Create backward"); 

pthread_exit(NULL); 
}
#include <pthread.h>
#include "error.h"
#include <errno.h>

#define ITERATIONS 100


pthread_mutex_t mutex[3] = {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER
};

int backoff = 1;
int yield_flag = 0;

void* lock_forward(void* arg)
{
int i, iterate, backoffs;
int status;

for(iterate = 0; iterate < ITERATIONS; iterate++)
{
backoffs = 0;
for(i = 0; i < 3; i++){
if(i == 0)
{
status = pthread_mutex_lock(&mutex[i]);
if(status != 0)
ERROR_ABORT(status,"Lock mutex");
}else
{
if(backoff)
status = pthread_mutex_trylock(&mutex[i]);
else
status = pthread_mutex_lock(&mutex[i]);

if(status == EBUSY)
{
backoff++;
printf("forward locker backing off at %d.\n", i);
for(; i >= 0; i--)
{
status = pthread_mutex_unlock(&mutex[i]);
if(status != 0)
ERROR_ABORT(status, "Unlock mutex");
}
}else
{
if(status != 0)
ERROR_ABORT(status, "Lock mutex");

printf("forward locker got %d \n", i);
}
}

if(yield_flag){
if(yield_flag > 0)
sched_yield();
else
sleep(1);
}
}

printf("lock forward got all locks , %d backoffs\n", backoffs);

pthread_mutex_unlock(&mutex[2]);
pthread_mutex_unlock(&mutex[1]);
pthread_mutex_unlock(&mutex[0]);
sched_yield();
}

return NULL;
}

void* lock_backward(void* arg)
{
int i, iterate, backoffs;
int status;

for(iterate = 0; iterate < ITERATIONS; iterate++)
{
backoffs = 0;
for(i = 2; i >= 0; i--){
if(i == 2)
{
status = pthread_mutex_lock(&mutex[i]);
if(status != 0)
ERROR_ABORT(status,"Lock mutex");
}else
{
if(backoff)
status = pthread_mutex_trylock(&mutex[i]);
else
status = pthread_mutex_lock(&mutex[i]);

if(status == EBUSY)
{
backoff++;
printf("backward locker backing off at %d.\n", i);
for(; i < 3; i++)
{
status = pthread_mutex_unlock(&mutex[i]);
if(status != 0)
ERROR_ABORT(status, "Unlock mutex");
}
}else
{
if(status != 0)
ERROR_ABORT(status, "Lock mutex");

printf("backward locker got %d \n", i);
}
}

if(yield_flag){
if(yield_flag > 0)
sched_yield();
else
sleep(1);
}
}

printf("lock backward got all locks , %d backoffs\n", backoffs);

pthread_mutex_unlock(&mutex[0]);
pthread_mutex_unlock(&mutex[1]);
pthread_mutex_unlock(&mutex[2]);
sched_yield();
}


return NULL;
}

int main(int argc, char* argv[])
{
pthread_t forward, backward;
int status;

if(argc > 1)
backoff = atoi(argv[1]);

if(argc > 2)
yield_flag = atoi(argv[2]);

status = pthread_create(&forward, NULL, lock_forward, NULL);
if(status != 0)
ERROR_ABORT(status, "Create forward");

status = pthread_create(&backward, NULL, lock_backward, NULL);
if(status != 0)
ERROR_ABORT(status, "Create backward");

pthread_exit(NULL);
}

锁定链

一般用于遍历数据结果(树,链表),一个用于锁定指针,一个锁定数据。
形如:
pthread_mutex_lock(&mutex_a);
pthread_mutex_lock(&mutex_b);
...
pthread_mutex_unlock(&mutex_a)
...
pthread_mutex_unlock(&mutex_b)
注意,锁定链往往会出现大量的锁定和解锁操作,有时会得不偿失。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值