#include
#include
#include
#include
#include
void *fun(void *arg)
{
char arr[] = "1 2 3 4 5 6 7 8";
char *p = strtok(arr, " ");
while (p != NULL)
{
printf("p=%s\n", p);
sleep(1);
p = strtok(NULL, " ");
}
}
int main()
{
pthread_t id;
pthread_create(&id, NULL, fun, NULL);
char str[] = "a b c d e f g h";
char *s = strtok(str, " ");
while (s != NULL)
{
printf("s=%s\n", s);
sleep(1);
s = strtok(NULL, " ");
}
pthread_join(id, NULL);
exit(0);
}
char *strtok_r(char *str, const char *delim, char **saveptr);
这里我们专门申请一个指针用来存储当前字符串的下一个位置,防止出现混乱。
#include
#include
#include
#include
#include
void *fun(void *arg)
{
char arr[] = "1 2 3 4 5 6 7 8";
char*ptr=NULL;
char *p = strtok_r(arr, " ",&ptr);
while (p != NULL)
{
printf("p=%s\n", p);
sleep(1);
p = strtok_r(NULL, " ",&ptr);
}
}
int main()
{
pthread_t id;
pthread_create(&id, NULL, fun, NULL);
char str[] = "a b c d e f g h";
char*ptr=NULL;
char *s = strtok_r(str, " ",&ptr);
while (s != NULL)
{
printf("s=%s\n", s);
sleep(1);
s = strtok_r(NULL, " ",&ptr);
}
pthread_join(id, NULL);
exit(0);
}
如果该函数实现的功能中有静态变量或者全局变量时,要考虑是否满足于多线程当中。
定义三个信号量用于控制字符的打印,设置其初始值为1,0,0,因为刚开始要打印a,那么该信号量应该为1,这样就能让a的线程去p操作,进而让其余线程等待v操作的出现。有点类似于单循环链表的感觉。
#include
#include
#include
#include
#include
#include
sem_t sem1;
sem_t sem2;
sem_t sem3;
void *funa(void *arg)
{
for (int i = 0; i < 5; i++)
{
sem_wait(&sem1);
printf("a");
fflush(stdout);
sleep(1);
sem_post(&sem2);
}
}
void *funb(void *arg)
{
for (int i = 0; i < 5; i++)
{
sem_wait(&sem2);
printf("b");
fflush(stdout);
sleep(1);
sem_post(&sem3);
}
}
void *func(void *arg)
{
for (int i = 0; i < 5; i++)
{
sem_wait(&sem3);
printf("c");
fflush(stdout);
sleep(1);
sem_post(&sem1);
}
}
int main()
{
pthread_t id1, id2, id3;
sem_init(&sem1, 0, 1);
sem_init(&sem2, 0, 0);
sem_init(&sem3, 0, 0);
pthread_create(&id1, NULL, funa, NULL);
pthread_create(&id2, NULL, funb, NULL);
pthread_create(&id3, NULL, func, NULL);
pthread_join(id1, NULL);
pthread_join(id2, NULL);
pthread_join(id3, NULL);
sem_destroy(&sem1);
sem_destroy(&sem2);
sem_destroy(&sem3);
exit(0);
}
场景:大部分情况都是读的线程,少部分写,但完全可以同时读,也不会改变临界资源,而如果全用互斥锁,则程序的性能就会下降
区别:假如有多个读的线程,少部分写,在读的线程都加读锁,其它有读锁的线程也能读,没读锁的线程读不了,而加上写锁,其它读锁写锁都不能用,只能阻塞住。
API函数
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//读锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//销毁锁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);//初始化锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁
#include
#include
#include
#include
#include
#include
pthread_rwlock_t rwlock;
void *fun1(void *arg)
{
for (int i = 0; i < 10; i++)
{
pthread_rwlock_rdlock(&rwlock);
printf("fun1 read start\n");
sleep(1);
printf("fun1 read end\n");
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
void *fun2(void *arg)
{
for (int i = 0; i < 10; i++)
{
pthread_rwlock_rdlock(&rwlock);
printf("fun2 read start\n");
sleep(3);
printf("fun2 read end\n");
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
void* fun3(void *arg)
{
for (int i = 0; i < 10; i++)
{
pthread_rwlock_wrlock(&rwlock);
printf("------write start\n");
sleep(3);
printf("-------write end\n");
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
int main()
{
pthread_rwlock_init(&rwlock, NULL);
pthread_t id1, id2, id3;
pthread_create(&id1, NULL, fun1, NULL);
pthread_create(&id1, NULL, fun2, NULL);
pthread_create(&id1, NULL, fun3, NULL);
pthread_join(id1, NULL);
pthread_join(id2, NULL);
pthread_join(id3, NULL);
pthread_rwlock_destroy(&rwlock);
exit(0);
}
截取部分结果
在执行写锁的时候不能出现读取操作,同样在执行读取操作的时候不能有写的操作。
条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待这个共享数据的线程。
主程序给消息队列的线程发送消息,唤醒线程
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_signal(pthread_cond_t *cond); //唤醒单个线程
int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒所有等待的线程
int pthread_cond_destroy(pthread_cond_t *cond);
个人理解:就是你把线程放在wait等待队列中,阻塞住,然后当你满足个条件时,你就把放进去的线程从等待队列中拿出来用。而下面的代码案例中,则是创建两个线程,然后进入while循环不断的把自己放在wait队列中,当主函数满足条件,则随便从wait队列中拿一个线程用,用完了后然后自己又循环回来,把自己加入到wait等待队列中
#include
#include
#include
#include
#include
pthread_mutex_t mutex;
pthread_cond_t cond;
void* funa(void* arg)
{
char* s = (char*)arg;
while(1)
{
//加锁是为了能有个同步
pthread_mutex_lock(&mutex);//如果这锁没人加,则能通过
pthread_cond_wait(&cond,&mutex);//加入条件变量的等待队列 --阻塞 然后释放锁 等自己被唤醒时,加锁,看有没有人出或者入,再出队列
pthread_mutex_unlock(&mutex);
if (strncmp(s,"end",3) == 0)
{
break;
}
printf("A thread read:%s",s);
}
}
void* funb(void *arg)
{
char* s = (char*)arg;
while(1)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex); //加入等待队列
pthread_mutex_unlock(&mutex);
if (strncmp(s,"end",3) == 0)
{
break;
}
printf("B thread read:%s",s);
}
}
int main()
{
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
char buff[128] = {0};
pthread_t ida,idb;
pthread_create(&ida,NULL,funa,buff);
pthread_create(&idb,NULL,funb,buff);
while(1)
{
fgets(buff,128,stdin);
if(strncmp(buff,"end",3) == 0 )
{
pthread_cond_broadcast(&cond);
break;
}
else
{
pthread_cond_signal(&cond);
}
}
pthread_join(ida,NULL);
pthread_join(idb,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
exit(0);
}