多线程同步机制
Posted xiang-yin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程同步机制相关的知识,希望对你有一定的参考价值。
1, spinlock
适合短暂的等待,不值得休眠的那种短暂.
jmp 11b 12: get_lock: lock bts $0, 0x6000 jc get_lock lock incw smp_cpus mov $smp_cpus, %bx lock btr $0, 0x6000 /*release lock*/ mov 0(%bx), %si ... smp_ap_boot_code_end:
这是每个核启动后,根据smp_cpus获取自己的核编号,从而在屏幕上定位不同的"点",然后循环递增其ascii码.
2, atomic_t
这是linux内核提供的原子数,相应的有atomic_inc/dec()一系列方法.
x86上,其内部实现依赖于lock指令前缀.
3,semaphore
sem_init(); sem_wait(); sem_post(); sem_destroy();
如果想fork()后仍然使用,需要利用共享内存区.
另外每次post之后,只唤醒队列里的一个进程.因为等待队列里的进程肯定都是因为sem_wait()进入的,他们自然都会调用sem_post()叫"下一个".
SO上的一篇特别好:
https://stackoverflow.com/questions/16400820/how-to-use-posix-semaphores-on-forked-processes-in-c
How to use POSIX semaphores on forked processes in C?
I want to fork multiple processes and then use a semaphore on them. Here is what I tried:
sem_init(&sem, 1, 1); /* semaphore*, pshared, value */ . . . if(pid != 0){ /* parent process */ wait(NULL); /* wait all child processes */ printf(" Parent: All children have exited. "); . . /* cleanup semaphores */ sem_destroy(&sem); exit(0); } else{ /* child process */ sem_wait(&sem); /* P operation */ printf(" Child(%d) is in critical section. ",i); sleep(1); *p += i%3; /* increment *p by 0, 1 or 2 based on i */ printf(" Child(%d) new value of *p=%d. ",i,*p); sem_post(&sem); /* V operation */ exit(0); }
.....一个高赞回答:The problem you are facing is the misunderstanding of
sem_init()
function. When you read the manual page you will see this:The pshared argument indicates whether this semaphore is to be shared between the threads of a process, or between processes.
If you are done reading up to this point, you will think that the non-zero value of pshared will make the semaphore inter-process semaphore. However, this is wrong. You should continue reading and you‘ll understand that you have to locate the semaphore in a shared memory region. To do that, several functions can be used as you can see below:
If pshared is nonzero, then the semaphore is shared between processes, and should be located in a region of shared memory (see shm_open(3), mmap(2), and shmget(2)). (Since a child created by fork(2) inherits its parent‘s memory mappings, it can also access the semaphore.) Any process that can access the shared memory region can operate on the semaphore using sem_post(3), sem_wait(3), etc.
I find this approach as a more complicated approach than others, therefore I want to encourage people to use
sem_open()
instead ofsem_init()
.Below you can see a complete program illustrates the following:
- How to allocate shared memory and use shared variables between forked processes.
- How to initialize a semaphore in a shared memory region and is used by multiple processes.
- How to fork multiple processes and make the parent wait until all of its children exit.
#include <stdio.h> /* printf() */ #include <stdlib.h> /* exit(), malloc(), free() */ #include <sys/types.h> /* key_t, sem_t, pid_t */ #include <sys/shm.h> /* shmat(), IPC_RMID */ #include <errno.h> /* errno, ECHILD */ #include <semaphore.h> /* sem_open(), sem_destroy(), sem_wait().. */ #include <fcntl.h> /* O_CREAT, O_EXEC */ int main (int argc, char **argv){ int i; /* loop variables */ key_t shmkey; /* shared memory key */ int shmid; /* shared memory id */ sem_t *sem; /* synch semaphore *//*shared */ pid_t pid; /* fork pid */ int *p; /* shared variable *//*shared */ unsigned int n; /* fork count */ unsigned int value; /* semaphore value */ /* initialize a shared variable in shared memory */ shmkey = ftok ("/dev/null", 5); /* valid directory name and a number */ printf ("shmkey for p = %d ", shmkey); shmid = shmget (shmkey, sizeof (int), 0644 | IPC_CREAT); if (shmid < 0){ /* shared memory error check */ perror ("shmget "); exit (1); } p = (int *) shmat (shmid, NULL, 0); /* attach p to shared memory */ *p = 0; printf ("p=%d is allocated in shared memory. ", *p); /********************************************************/ printf ("How many children do you want to fork? "); printf ("Fork count: "); scanf ("%u", &n); printf ("What do you want the semaphore value to be? "); printf ("Semaphore value: "); scanf ("%u", &value); /* initialize semaphores for shared processes */ sem = sem_open ("pSem", O_CREAT | O_EXCL,