This is an old topic , But basically, most of the discussions went astray .

The core of most discussions is How to design a lock to synchronize the access of shared variables . This is, in fact, putting the cart before the horse :

* We need to design an overpass , Not to design a traffic light !
in fact , Multithreaded programming should not access shared variables , If you really want to access shared variables in multiple threads , The only efficient solution is Strictly control the time sequence .
Yeah , First come first served is the only way . As for designing locks like this and that , It's all lazy politics , Just in case something goes wrong .

As early as 100 Many years ago , It can transmit different voice paths on the same telephone line , This benefits from the strict slot allocation and multiplexing mechanism , Later, the times improved , Things got worse , This is entirely due to another way of slot multiplexing , That is slot statistics multiplexing . Modern operating system and modern packet switching network are the practical practitioners of this multiplexing mode .

I don't think statistical reuse is an efficient way , It may just be a solution that has to be adopted in the face of diversified scenarios . in my opinion , If we just talk about efficiency , There is nothing better than strict slot multiplexing .

Let me give you an example .4 Threads accessing shared variables .

First, let's look at a slightly more rigorous solution , Strictly assign access order :
#include <stdio.h> #include <pthread.h> #include <semaphore.h> sem_t sem1;
sem_t sem2; sem_t sem3; sem_t sem4; unsigned long cnt = 0; #define TARGET
0xffffff void do_work() { int i; for(i = 0; i < TARGET; i++) { cnt ++; } } void
worker_thread1(void) { sem_wait(&sem1); do_work(); sem_post(&sem2); } void
worker_thread2(void) { sem_wait(&sem2); do_work(); sem_post(&sem3); } void
worker_thread3(void) { sem_wait(&sem3); do_work(); sem_post(&sem4); } void
worker_thread4(void) { sem_wait(&sem4); do_work(); printf("%lx\n", cnt); exit(0)
; } int main() { pthread_t id1 ,id2, id3, id4; sem_init(&sem1, 0, 0); sem_init(&
sem2, 0, 0); sem_init(&sem3, 0, 0); sem_init(&sem4, 0, 0); pthread_create(&id1,
NULL, (void *)worker_thread1, NULL); pthread_create(&id2, NULL, (void *)
worker_thread2, NULL); pthread_create(&id3, NULL, (void *)worker_thread3, NULL);
pthread_create(&id4, NULL, (void *)worker_thread4, NULL); sem_post(&sem1);
getchar(); return 0; }
Then let's look at a more general approach , That is, lock scheme :
#include <stdio.h> #include <pthread.h> pthread_spinlock_t spinlock; unsigned
long cnt = 0; #define TARGET 0xffffff void do_work() { int i; for(i = 0; i <
TARGET; i++) { pthread_spin_lock(&spinlock); cnt ++; pthread_spin_unlock(&
spinlock); } if (cnt == 4*TARGET) { printf("%lx\n", cnt); exit(0); } } void
worker_thread1(void) { do_work(); } void worker_thread2(void) { do_work(); }
void worker_thread3(void) { do_work(); } void worker_thread4(void) { do_work();
} int main() { pthread_t id1 ,id2, id3, id4; pthread_spin_init(&spinlock, 0);
pthread_create(&id1, NULL, (void *)worker_thread1, NULL); pthread_create(&id2,
NULL, (void *)worker_thread2, NULL); pthread_create(&id3, NULL, (void *)
worker_thread3, NULL); pthread_create(&id4, NULL, (void *)worker_thread4, NULL);
getchar(); }
Now compare the efficiency differences between the two :
[root@localhost linux]# time ./pv 3fffffc real 0m0.171s user 0m0.165s sys
0m0.005s[root@localhost linux]# time ./spin 3fffffc real 0m4.852s user
0m19.097s sys 0m0.035s
Contrary to intuition , Maybe you think , The first example is that it degenerates into serial operation ? Isn't the advantage of multiprocessor lost ? The second is the correct posture of multithreading programming !

in fact , For shared variables , In any case, it must be accessed serially . This kind of code can't be multithreaded at all . therefore , Real multi thread programming :

* Be sure to eliminate shared variables .
* If you have to share variables , Then we must strictly control the access sequence , Instead of locking to control concurrency .
Now let's see Linux kernel , a large number of spinlock It's not really multithreading the kernel , And purely for the sake of “ If not introduced spinlock There will be problems …”

RSS,percpu
spinlock It seems to be the right way , But if you want to have been kneaded into a mess Linux Kernel's complete serialization of shared variables , It doesn't seem easy , What's more? , Interrupt cannot control its timing , How about threading interrupt processing ? It seems that the effect is not very good .

Concurrency efficiency issues encountered , If you design a big lock , In fact, you admit the problem, but you don't want to solve it , This is a negative response .

lock , root of all evils . It's true to cancel shared variables or control timing .

that , What is the difference ? The difference is just a suit .

Wet leather shoes in Wenzhou, Zhejiang Province , If it rains, you won't get fat .

Technology