
pthread_key_t myWinKey;
/ *函数createWindow * /
void createWindow(void){
Fl_Window *获胜;
静态pthread_once_t一次= PTHREAD_ONCE_INIT;
/ *调用函数createMyKey创建密钥* /
pthread_once(&一次,createMyKey);
/ * win指向新创建的窗口* /
win = new Fl_Window(0,0,100,100,“ MyWindow”);
/ *为此窗口进行一些可能的设置,例如大小,位置,名称等. * /
setWindow(win);
/ *将窗口指针值绑定到键myWinKey * /
pthread_setpecific(myWinKey,win);
}
/ *函数createMyKey创建一个密钥并指定析构函数* /
void createMyKey(void){
pthread_keycreate(&myWinKey,freeWinKey);
}
/ *功能freeWinKey,释放空间* /
void freeWinKey(Fl_Window * win){

删除胜利;
}
这样,在不同的线程中调用函数createMyWin,就可以在该线程中看到window变量,该变量是由pthread_getspecific函数获得的. 在上面的示例中,我们使用了pthread_setspecific函数将线程数据与键绑定. 这两个函数的原型如下:
int pthread_setspecific __P((pthread_key_t __key,__ const void * __ pointer));此函数设置特定于线程的数据的值,并将其分配给pthread_key_create创建的键. 如果调用成功,则返回值为0,否则返回错误代码.
无效* pthread_getspecific __P((pthread_key_t __key));此函数获取绑定到指定键的值. 调用成功,并返回与给定参数键对应的数据. 如果没有数据连接到密钥,则返回NULL.
这两个功能的含义和用法很明显. 应该注意的是,当使用pthread_setspecific为键指定新线程数据时,必须释放原始线程数据以回收空间. 此过程函数pthread_key_delete用于删除密钥,该密钥所占用的内存将被释放,但也应注意,它仅释放该密钥所占用的内存,而不释放线程数据所占用的内存资源. 与键相关联pthread_create函数参数,并且它不会触发函数pthread_key_create中定义的析构函数. 线程数据的释放必须在释放密钥之前完成.
2. 互斥锁
假设每个现成的文件都将数据顺序写入同一文件,那么最终结果是难以想象的. 因此,请使用互斥量来确保只有一个线程在一段时间内执行一段代码.
使用int pthread_mutex_lock锁定互斥锁,使用int pthread_mutex_unlock解锁.
如果我们尝试锁定已被另一个线程锁定的互斥锁,则该程序将阻塞,直到该互斥锁被解锁为止.
如果在共享内存中分配了互斥锁,则必须在运行时调用ptgread_mutex_init函数对其进行初始化.
void reader_function(void);
void writer_function(void);
字符缓冲区;
int buffer_has_item = 0;
pthread_mutex_t互斥锁;
struct timespec延迟;
void main(void){
pthread_t阅读器;
/ *定义延迟时间* /

delay.tv_sec = 2;
delay.tv_nec = 0;
/ *使用默认属性初始化互斥对象* /
pthread_mutex_init(&mutex,NULL);
pthread_create(&reader,pthread_attr_default,(void *)&reader_function),NULL);
writer_function();
}
void writer_function(void){
while(1){
/ *锁定互斥锁* /
pthread_mutex_lock(&mutex);
如果(buffer_has_item == 0){
buffer = make_new_item();
buffer_has_item = 1;
}
/ *打开互斥锁* /
pthread_mutex_unlock(&mutex);
pthread_delay_np(&delay);
}
}

void reader_function(void){
while(1){
pthread_mutex_lock(&mutex);
if(buffer_has_item == 1){
consume_item(buffer);
buffer_has_item = 0;
}
pthread_mutex_unlock(&mutex);
pthread_delay_np(&delay);
}
}
函数pthread_mutex_init用于生成互斥量. NULL参数指示使用默认属性. 如果需要声明特定的属性互斥锁,则必须调用函数pthread_mutexattr_init. 函数pthread_mutexattr_setpshared和函数pthread_mutexattr_settype用于设置互斥锁的属性. 上一个函数设置属性pshared,该属性具有两个值PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED. 前者用于同步不同进程中的线程,后者用于同步进程中的不同线程. 在上面的示例中,我们使用了默认属性PTHREAD_PROCESS_ PRIVATE. 后者用于设置互斥锁的类型. 可用的类型为PTHREAD_MUTEX_NORMAL,PTHREAD_MUTEX_ERRORCHECK,PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT. 它们分别定义了不同的访问和解锁机制. 通常,最后一个默认属性是选中的.
应该注意的是,在使用互斥锁的过程中,很可能会发生死锁: 两个线程试图同时占用两个资源,并以不同的顺序锁定相应的互斥锁,例如,两个线程需要锁定互斥锁1和互斥锁2,首先是线程锁定互斥锁1,首先是b线程锁定互斥锁2,然后发生死锁. 目前,我们可以使用函数pthread_mutex_trylock,它是函数pthread_mutex_lock的非阻塞版本. 当发现死锁不可避免时,它将返回相应的信息,程序员可以相应地处理死锁. 此外,不同类型的互斥锁对死锁的处理方式也不同,但是最重要的是程序员在编程时要注意这一点.
3. 条件变量
互斥锁的一个明显缺点是它只有两个状态: 锁定和解锁. 条件变量通过允许线程阻塞并等待另一个线程发送信号来弥补互斥量的不足. 它通常与互斥锁一起使用. 使用时,条件变量用于阻塞线程. 当不满足条件时,线程通常会解锁相应的互斥锁并等待条件更改. 一旦某个其他线程更改了条件变量,它将通知相应的条件变量唤醒被该条件变量阻止的一个或多个线程. 这些线程将重新锁定互斥锁并重新测试是否满足条件. 通常,条件变量用于同步线轴承.
条件变量的结构为pthread_cond_t,函数pthread_cond_init()用于初始化条件变量. 它的原型是:
int pthread_cond_init __P((pthread_cond_t * __ cond,__ const pthread_condattr_t * __ cond_attr));
其中pthread_create函数参数,cond是指向结构pthread_cond_t的指针,而cond_attr是指向结构pthread_condattr_t的指针. 结构pthread_condattr_t是条件变量的属性结构. 与互斥锁一样,我们可以使用它来设置条件变量在进程内还是进程间可用. 默认值为PTHREAD_ PROCESS_PRIVATE,即,该条件变量由同一进程中的每个线程使用. 请注意,初始化条件变量仅在不使用时才能重新初始化或释放.
在pthread中,条件变量是类型为pthread_cond_t的变量. 条件变量使用以下两个函数:
pthread_cond_wait函数用于阻止. 可以通过函数pthread_cond_signal和函数pthread_cond_broadcast唤醒线程,但应注意,条件变量仅用于阻塞和唤醒线程,并且用户需要指定特定的判断条件,例如是否变量是0,依此类推,可以从下面的示例中看到. 线程唤醒后,它将重新检查以查看是否满足条件. 通常,如果未满足要求,则该线程仍应在此处被阻塞,等待下一次唤醒. 该过程通常使用while语句来实现.

另一个用于阻塞线程的函数是pthread_cond_timedwait(). 它比函数pthread_cond_wait()多了一个时间参数. 在缺席时间段之后,即使不满足条件变量,也会解除阻塞.
函数pthread_cond_signal()用于释放在条件变量cond中阻塞的线程.
函数pthread_cond_broadcast(pthread_cond_t * cond)用于唤醒在条件变量cond上阻塞的所有线程. 这些线程唤醒后,它们将再次竞争相应的互斥锁,因此您必须谨慎使用此功能.
以下是使用函数pthread_cond_wait()和函数pthread_cond_signal()的简单示例:
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
无符号数;
decrement_count(){
pthread_mutex_lock(&count_lock);
while(count == 0)
pthread_cond_wait(&count_nonzero,&count_lock);
count = count -1;
pthread_mutex_unlock(&count_lock);
}
increment_count(){
pthread_mutex_lock(&count_lock);
if(count == 0)
pthread_cond_signal(&count_nonzero);
count = count + 1;
pthread_mutex_unlock(&count_lock);
}
当计数值为0时,递减函数在pthread_cond_wait被阻止,并且count_lock互斥锁打开. 这时,当调用increasing_count函数时,pthread_cond_signal()函数将更改条件变量,告知decrement_count()停止阻塞.
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-283423-1.html
我们家千玺配的棒棒的