多线程同步机制中的读写锁(Read-Write Lock)是一种特殊的锁机制,用于控制对共享资源的读写访问。读写锁允许多个线程同时读取共享资源,但在写操作时需要独占访问。
读写锁的基本原则是:多个线程可以同时获取读锁,但只有一个线程可以获取写锁。当有线程持有写锁时,其他线程无法获取读锁或写锁,直到写操作完成并释放写锁。
读写锁有两种状态:读模式下加锁状态(读锁),写模式下加锁状态(写锁)。读写锁只有一把。
1. 读写锁的特性: 写独占,读共享。
读写锁并行阻塞,写锁优先级高。
2. 读写锁相关函数:
3. 示例代码:
下面代码设置一个写进程 和 三个读进程区访问共享资源。
(void*)i 将整数 i 转换为 void* 类型。在线程的函数中,需要将其转换回整数类型,以便使用它。可以使用 (int)arg 将 void* 转换回 int 类型。void* 是一种通用的泛型指针,可以在不关心具体类型的情况下进行转换和操作。
#include
#include
#include
#include
#include
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; // 初始化读写锁
int data = 1;
void *write_thread (void *arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
data += 1;
printf("write : data = %d\n",data);
pthread_rwlock_unlock(&rwlock);
sleep(rand() %3); // 随机休眠,让出 cpu资源
}
pthread_exit(NULL);
}
void *read_thread (void *arg)
{
int i = (int )arg;
while(1)
{
pthread_rwlock_rdlock(&rwlock);
printf("read %d : data = %d\n",i, data);
pthread_rwlock_unlock(&rwlock);
sleep(rand() %3);
}
pthread_exit(NULL);
}
int main(void)
{
pthread_t r_tid[5], w_tid;
srand(time(NULL));
// 创建多个读线程
for (int i = 0; i < 3; i++)
{
pthread_create(&r_tid[i], NULL, read_thread, (void*)i);
}
pthread_create(&w_tid, NULL, write_thread, NULL);
for(int j=0;j<3;j++)
pthread_join(r_tid[j],NULL);
pthread_join(w_tid,NULL);
pthread_rwlock_destroy(&rwlock);
return 0;
}
在多线程编程中,条件变量是一种用于线程之间进行通信和同步的机制。条件变量允许一个线程等待特定的条件发生,并在条件满足时通知其他线程继续执行。条件变量本身不是锁。
条件变量常与互斥锁(mutex)结合使用,以实现线程之间的同步操作。
1. 相关函数:
(1) 对条件变量进行初始化,并可指定属性。通常使用默认属性,可以传入 NULL。
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
(2) 销毁条件变量,释放相关资源。
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
(3) 通知等待在条件变量上的一个线程,使其继续执行。如果有多个线程等待,只通知其中一个线程。
int pthread_cond_signal(pthread_cond_t *cond);
(4) 通知所有等待在条件变量上的线程,使它们都继续执行。
int pthread_cond_broadcast(pthread_cond_t *cond) ;
2. 示例代码:
描述生产者 和 消费者的关系。
#include
#include
#include
#include
struct msg
{
int num;
struct msg* pnext;
};
struct msg *head = NULL;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *producer_thread (void *arg) // 生产者线程
{
while(1)
{
struct msg *info = malloc(sizeof(struct msg));
info->num = rand() % 1000 + 1;
pthread_mutex_lock(&mutex);
info->pnext = head;
head = info;
pthread_mutex_unlock(&mutex);
// 唤醒阻塞的线程
pthread_cond_signal(&cond);
printf("--------------------- producer : %d\n",info->num);
sleep(rand() % 3);
}
return NULL;
}
void *customer_thread (void *arg) // 消费者线程
{
while(1)
{
struct msg *info;
pthread_mutex_lock(&mutex);
if(head == NULL)
{
pthread_cond_wait(&cond, &mutex); // 阻塞线程,等待有数据。
}
info = head;
head = info->pnext;
pthread_mutex_unlock(&mutex);
printf("customer : =============== %d\n",info->num);
free(info);
info = NULL;
sleep(rand() % 3);
}
return NULL;
}
int main(void)
{
pthread_t pid,cid;
srand(time(NULL)); // 设置随机种子
int ret = pthread_create(&pid, NULL, producer_thread, NULL);
if(ret != 0)
{
printf("prodecer_thread_create error\n");
}
ret = pthread_create(&cid, NULL, customer_thread, NULL);
if(ret != 0)
{
printf("consumer_thread_create error\n");
}
pthread_join(pid, NULL); // 等待回收线程,获取退出线程的状态
pthread_join(cid, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}