Linux 多线程同步(信号量)

时间:2023-02-21 21:29:57

 sem_wait函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,这信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就 会地等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加 一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。

sem_post函数的作用是给信号量的值加上一个“1”,它是一个“原子操作”---即同时对同一个信号量做加“1”操作的两个线程是不会冲突的;而同 时对同一个文件进行读、加和写操作的两个程序就有可能会引起冲突。信号量的值永远会正确地加一个“2”--因为有两个线程试图改变它。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

int myglobal;
sem_t sem;

void * thread_function(void *arg)
{
int i,j;
for (i = 0; i < 10; i += 1)
{
sem_wait(&sem);
j = myglobal;
j = j+1;
printf(".");
fflush(stdout);
sleep(1);
myglobal = j;
sem_post(&sem);
}
return NULL;
}


int main(void)
{
pthread_t mythread;
int i;

sem_init(&sem, 0, 1);//信号量初始化
if(pthread_create(&mythread, NULL, thread_function, NULL))
{
printf("create thread error!\n");
abort();
}

/* sleep(1);*/

for(i = 0; i < 10; i++)
{
sem_wait(&sem);//=0
myglobal = myglobal + 1;
printf("o");
fflush(stdout);
sleep(1);
sem_post(&sem);//=1
}

if(pthread_join(mythread, NULL))
{
printf("waiting thread failed!\n");
abort();
}

printf("myglobal equals %d\n",myglobal);

exit(0);
}

例子2:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

void * thread_function(void * arg);
sem_t bin_sem;

#define WORK_SIZE 1024
char work_area[WORK_SIZE];

int main(int argc, char const *argv[])
{
int res;
pthread_t pthread;
void * thread_result;

res = sem_init(&bin_sem,0,0);//step 1
if (res != 0)
{
perror("sem_init failed!");
exit(EXIT_FAILURE);
}

res = pthread_create(&pthread,NULL,thread_function,NULL);//step 2
if (res != 0)
{
perror("pthread_create failed!");
exit(EXIT_FAILURE);
}

printf("input some text. Enter end to finish\n");
while(strncmp("end",work_area,3) != 0)
{
fgets(work_area,WORK_SIZE,stdin);
sem_post(&bin_sem);//step 3
}
printf("the final work_area is : %s\n",work_area);//the result is end that reflect every time work_area overload
res = pthread_join(pthread,&thread_result);
if (res != 0)
{
perror("pthread_join failed!");
exit(EXIT_FAILURE);
}

sem_destroy(&bin_sem);
exit(EXIT_SUCCESS);
}

void *thread_function(void * arg)
{
sem_wait(&bin_sem);//if sem value equals 0,and wait,else run
while(strncmp("end",work_area,3) != 0)
{
printf("you input %d characters\n",strlen(work_area)-1);//remove the enter key
sem_wait(&bin_sem);//if sem value equals 0,and wait,else run
}
pthread_exit(NULL);
}

保证线程之间的同步!