


Apakah beberapa kaedah penyegerakan berbilang benang dalam Linux?
Kaedah penyegerakan termasuk: 1. Kunci Mutex ialah pembolehubah global khas dengan dua keadaan: kunci dan buka kunci Kunci mutex boleh diperolehi oleh benang tertentu Apabila kunci mutex dipegang oleh benang tertentu , mutex akan dikunci dan menjadi keadaan kunci Selepas itu, hanya benang yang mempunyai kuasa untuk membuka kunci 2. Kunci putaran adalah gelung tak terhingga 3. Semafor digunakan untuk mengawal bilangan utas yang mengakses sumber kongsi terhad; 4. Pembolehubah keadaan 5. Kunci baca-tulis;
Persekitaran pengendalian tutorial ini: sistem linux7.3, komputer Dell G3.
Penyegerakan benang bermaksud bahawa apabila utas beroperasi pada sumber kritikal, tiada utas lain boleh beroperasi pada sumber ini Sehingga utas menyelesaikan operasi, utas lain boleh beroperasi, iaitu, rentak yang diselaraskan, membenarkan utas untuk. dijalankan mengikut susunan yang telah ditetapkan. Terdapat 6 kaedah penyegerakan benang: kunci mutex, kunci putaran, semaphore, pembolehubah keadaan, kunci baca-tulis dan halangan.
Kaedah penyegerakan benang Linux
Berikut ialah contoh tidak selamat benang:
#include<stdio.h> #include<pthread.h> int ticket_num=10000000; void *sell_ticket(void *arg) { while(ticket_num>0) { ticket_num--; } } int main() { pthread_t t1,t2,t3; pthread_create(&t1, NULL, &sell_ticket, NULL); pthread_create(&t2, NULL, &sell_ticket, NULL); pthread_create(&t3, NULL, &sell_ticket, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); printf("ticket_num=%d\n", ticket_num); return 0; }
Hasil yang berjalan adalah seperti berikut:
# gcc no_lock_demo.c -o no_lock_demo.out -pthread # ./no_lock_demo.out ticket_num=-2
Hasil akhir tidak tetap dan mungkin 0 atau -1 penyegerakan benang perlu diperkenalkan untuk memastikan keselamatan benang.
Linux menyediakan pelbagai cara untuk mengendalikan penyegerakan benang, yang paling biasa digunakan ialah kunci mutex, kunci putaran dan semaphore.
1. Kunci Mutex
Intipati kunci mutex ialah pembolehubah global khas, yang mempunyai dua keadaan: kunci dan buka kunci Kunci mutex boleh dikawal oleh benang A tertentu memperolehnya Apabila mutex dipegang oleh benang, mutex akan dikunci dan bertukar menjadi keadaan kunci Selepas itu, hanya benang itu yang mempunyai kuasa untuk membuka kunci, dan benang lain yang ingin diperolehi mutex akan disekat , sehingga mutex dibuka.
Jenis kunci mutex:
Kunci biasa (PTHREAD_MUTEX_NORMAL): Jenis lalai kunci mutex. Apabila benang mengunci kunci biasa, benang selebihnya yang meminta kunci akan membentuk baris gilir menunggu dan mendapatkan kunci mengikut keutamaan selepas ia dibuka kunci Jenis kunci ini memastikan keadilan dalam peruntukan sumber. Jika benang mengunci kunci biasa yang telah dikunci semula, ia akan menyebabkan kebuntuan membuka kunci biasa yang telah dikunci oleh benang lain, atau membuka kunci biasa yang telah dibuka semula, akan membawa kepada akibat yang tidak dapat diramalkan.
Kunci semakan ralat (PTHREAD_MUTEX_ERRORCHECK): Jika benang mengunci kunci semakan ralat yang sudah dikunci semula, operasi mengunci mengembalikan EDEADLK untuk utas yang telah dikunci oleh utas lain Jika kunci pengesanan ralat dibuka kunci atau kunci pengesanan ralat yang sudah dibuka dibuka semula, operasi buka kunci kembali kepada EPERM.
Kunci bersarang (PTHREAD_MUTEX_RECURSIVE): Kunci ini membenarkan benang menguncinya beberapa kali sebelum melepaskan kunci tanpa kebuntuan jika utas lain ingin mendapatkan kunci ini, kunci semasa Pemilik mesti melakukan berbilang operasi buka kunci; untuk membuka kunci bersarang yang telah dikunci oleh benang lain, atau untuk membuka kunci bersarang lagi, operasi membuka kunci mengembalikan EPERM.
Kunci lalai (PTHREAD_MUTEX_DEFAULT): Jika benang mengunci kunci lalai yang sudah terkunci semula, atau membuka kunci lalai yang telah dikunci oleh benang lain, atau Membuka kunci kunci lalai yang tidak berkunci akan membawa kepada akibat yang tidak dapat diramalkan; kunci ini mungkin dipetakan kepada salah satu daripada tiga kunci di atas apabila dilaksanakan.
Kaedah berkaitan:
// 静态方式创建互斥锁 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 动态方式创建互斥锁,其中参数mutexattr用于指定互斥锁的类型,具体类型见上面四种,如果为NULL,就是普通锁。 int pthread_mutex_init (pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr); int pthread_mutex_lock(pthread_mutex_t *mutex); // 加锁,阻塞 int pthread_mutex_trylock(pthread_mutex_t *mutex); // 尝试加锁,非阻塞 int pthread_mutex_unlock(pthread_mutex_t *mutex); // 解锁
Contoh:
#include<stdio.h> #include<pthread.h> int ticket_num=10000000; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void *sell_ticket(void *arg) { while(ticket_num>0) { pthread_mutex_lock(&mutex); if(ticket_num>0) { ticket_num--; } pthread_mutex_unlock(&mutex); } } int main() { pthread_t t1,t2,t3; pthread_create(&t1, NULL, &sell_ticket, NULL); pthread_create(&t2, NULL, &sell_ticket, NULL); pthread_create(&t3, NULL, &sell_ticket, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); printf("ticket_num=%d\n", ticket_num); return 0; }
Kunci putaran
Seperti namanya, kunci putaran ialah gelung tak terhingga, mengundi secara berterusan Apabila benang tidak memperoleh kunci putaran, ia tidak akan memasuki keadaan tidur menyekat seperti kunci mutex, tetapi akan mengundi secara berterusan untuk memperoleh kunci Jika kunci putaran boleh dilepaskan dengan cepat, prestasi akan menjadi sangat tinggi Jika kunci putaran tidak dapat dilepaskan untuk jangka masa yang lama, atau terdapat sejumlah besar penyekatan IO, ia akan menyebabkan benang lain yang memperoleh kunci untuk mengundi. secara berterusan, mengakibatkan penggunaan CPU mencecah 100% terutamanya masa CPU.
Kaedah berkaitan:
int pthread_spin_init(pthread_spinlock_t *lock, int pshared); // 创建自旋锁 int pthread_spin_lock(pthread_spinlock_t *lock); // 加锁,阻塞 int pthread_spin_trylock(pthread_spinlock_t *lock); // 尝试加锁,非阻塞 int pthread_spin_unlock(pthread_spinlock_t *lock); // 解锁
Contoh:
#include<stdio.h> #include<pthread.h> int ticket_num=10000000; pthread_spinlock_t spinlock; void *sell_ticket(void *arg) { while(ticket_num>0) { pthread_spin_lock(&spinlock); if(ticket_num>0) { ticket_num--; } pthread_spin_unlock(&spinlock); } } int main() { pthread_spin_init(&spinlock, 0); pthread_t t1,t2,t3; pthread_create(&t1, NULL, &sell_ticket, NULL); pthread_create(&t2, NULL, &sell_ticket, NULL); pthread_create(&t3, NULL, &sell_ticket, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); printf("ticket_num=%d\n", ticket_num); return 0; }
3 Semaphore
Semaphore ialah pembilang , digunakan untuk mengawal bilangan utas yang mengakses sumber kongsi terhad.
Kaedah berkaitan:
// 创建信号量 // pshared:一般取0,表示调用进程的信号量。非0表示该信号量可以共享内存的方式,为多个进程所共享(Linux暂不支持)。 // value:信号量的初始值,可以并发访问的线程数。 int sem_init (sem_t* sem, int pshared, unsigned int value); int sem_wait (sem_t* sem); // 信号量减1,信号量为0时就会阻塞 int sem_trywait (sem_t* sem); // 信号量减1,信号量为0时返回-1,不阻塞 int sem_timedwait (sem_t* sem, const struct timespec* abs_timeout); // 信号量减1,信号量为0时阻塞,直到abs_timeout超时返回-1 int sem_post (sem_t* sem); // 信号量加1
Contoh:
#include<stdio.h> #include<pthread.h> #include <semaphore.h> int ticket_num=10000000; sem_t sem; void *sell_ticket(void *arg) { while(ticket_num>0) { sem_wait(&sem); if(ticket_num>0) { ticket_num--; } sem_post(&sem); } } int main() { sem_init(&sem, 0, 1); // value=1表示最多1个线程同时访问共享资源,与互斥量等价 pthread_t t1,t2,t3; pthread_create(&t1, NULL, &sell_ticket, NULL); pthread_create(&t2, NULL, &sell_ticket, NULL); pthread_create(&t3, NULL, &sell_ticket, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); printf("ticket_num=%d\n", ticket_num); return 0; }
4 Pembolehubah keadaan
Pembolehubah keadaan membolehkan memanggil The benang berjalan apabila syarat tertentu dipenuhi Apabila syarat tidak dipenuhi, benang terhalang dan menunggu untuk dibangkitkan. Ia mesti digunakan bersama dengan kunci mutex.
Pembolehubah bersyarat sering digunakan dalam model pengeluar dan pengguna.
Kaedah berkaitan:
pthread_cond_t cond=PTHREAD_COND_INITIALIZER; // 创建条件变量,一个互斥锁可以对应多个条件变量 int pthread_cond_wait (pthread_cond_t* cond,pthread_mutex_t* mutex); // 阻塞等待条件满足,同时释放互斥锁mutex int pthread_cond_timedwait (pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* abstime); // 带超时的阻塞等待条件满足,同时释放互斥锁mutex // 从条件变量cond中唤出一个线程,令其重新获得原先的互斥锁 // 被唤出的线程此刻将从pthread_cond_wait函数中返回,但如果该线程无法获得原先的锁,则会继续阻塞在加锁上。 int pthread_cond_signal (pthread_cond_t* cond); // 从条件变量cond中唤出所有线程 int pthread_cond_broadcast (pthread_cond_t* cond);
Contoh:
#include<stdio.h> #include<pthread.h> int max_buffer=10; int count=0; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; pthread_cond_t notempty=PTHREAD_COND_INITIALIZER; pthread_cond_t notfull=PTHREAD_COND_INITIALIZER; void *produce(void *args) { while(1) { pthread_mutex_lock(&mutex); while(count == max_buffer) { printf("buffer is full, wait...\n"); pthread_cond_wait(¬full, &mutex); } printf("produce ...\n"); count++; sleep(1); pthread_cond_signal(¬empty); pthread_mutex_unlock(&mutex); } } void *consumer(void *args) { while(1) { pthread_mutex_lock(&mutex); while(count == 0) { printf("buffer is empty, wait...\n"); pthread_cond_wait(¬empty, &mutex); } printf("consumer ...\n"); count--; sleep(1); pthread_cond_signal(¬full); pthread_mutex_unlock(&mutex); } } int main() { pthread_t t1,t2,t3,t4; pthread_create(&t1, NULL, &produce, NULL); pthread_create(&t2, NULL, &produce, NULL); pthread_create(&t3, NULL, &consumer, NULL); pthread_create(&t4, NULL, &consumer, NULL); pthread_join(t1, NULL); return 0; }
5、读写锁
读写锁可以有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的,当它以写模式锁住时,它是以独占模式锁住的,读读共享,读写互斥。
相关方法:
// 创建读写锁 pthread_rwlock_t rwlock=PTHREAD_RWLOCK_INITIALIZER; int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); // 加读锁,阻塞 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); // 加写锁,阻塞 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); // 释放读锁或者写锁 int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); // 尝试加读锁,非阻塞 int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); // 尝试加写锁,非阻塞
例子:
#include <stdio.h> #include <pthread.h> pthread_rwlock_t rwlock=PTHREAD_RWLOCK_INITIALIZER; void *read(void *arg) { while(1) { pthread_rwlock_rdlock(&rwlock); rintf("read message.\n"); sleep(1); pthread_rwlock_unlock(&rwlock); sleep(1); } } void *write(void *arg) { while(1) { pthread_rwlock_wrlock(&rwlock); printf("write message.\n"); sleep(1); pthread_rwlock_unlock(&rwlock); sleep(1); } } int main(int argc,char *argv[]) { pthread_t t1,t2,t3; pthread_create(&t1, NULL, &read, NULL); pthread_create(&t2, NULL, &read, NULL); pthread_create(&t3, NULL, &write, NULL); pthread_join(t1, NULL); return 0; }
6、屏障
屏障(barrier)是用户协调多个线程并行工作的同步机制。屏障允许每个线程等待,直到所有的合作线程都到达某一点,然后所有线程都从该点继续执行。pthread_join函数就是一种屏障,允许一个线程等待,直到另一个线程退出。但屏障对象的概念更广,允许任意数量的线程等待,直到所有的线程完成处理工作,而线程不需要退出,当所有的线程达到屏障后可以接着工作。
相关方法:
// 创建屏障 int pthread_barrier_init(pthread_barrier_t *barrier,const pthread_barrrierattr_t *attr,unsigned int count) // 阻塞等待,直到所有线程都到达 int pthread_barrier_wait(pthread_barrier_t *barrier)
例子:
#include <stdio.h> #include <pthread.h> pthread_barrier_t barrier; void *go(void *arg){ sleep (rand () % 10); printf("%lu is arrived.\n", pthread_self()); pthread_barrier_wait(&barrier); printf("%lu go shopping...\n", pthread_self()); } int main() { pthread_barrier_init(&barrier, NULL, 3); pthread_t t1,t2,t3; pthread_create(&t1, NULL, &go, NULL); pthread_create(&t2, NULL, &go, NULL); pthread_create(&t3, NULL, &go, NULL); pthread_join(t1, NULL); return 0; }
相关推荐:《Linux视频教程》
Atas ialah kandungan terperinci Apakah beberapa kaedah penyegerakan berbilang benang dalam Linux?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Ada masalah memuat naik fail di Google Chrome? Ini mungkin menjengkelkan, bukan? Sama ada anda melampirkan dokumen ke e -mel, berkongsi imej di media sosial, atau mengemukakan fail penting untuk kerja atau sekolah, proses muat naik fail yang lancar adalah penting. Jadi, ia boleh mengecewakan jika fail anda memuat naik terus gagal dalam Chrome pada Windows PC. Jika anda tidak bersedia untuk menyerahkan penyemak imbas kegemaran anda, berikut adalah beberapa petua untuk pembetulan yang tidak dapat memuat naik fail pada Windows Google Chrome 1. Mulailah dengan pembaikan sejagat sebelum kita belajar tentang sebarang petua penyelesaian masalah lanjutan, sebaiknya mencuba beberapa penyelesaian asas yang disebutkan di bawah. Penyelesaian Masalah Sambungan Internet: Sambungan Internet

Dalam sistem Linux, 1. Gunakan arahan IPA atau HostName-I untuk melihat IP peribadi; 2. Gunakan curlifconfig.me atau curlipinfo.io/ip untuk mendapatkan ip awam; 3. Versi desktop boleh melihat IP peribadi melalui tetapan sistem, dan penyemak imbas boleh mengakses laman web tertentu untuk melihat IP awam; 4. Perintah umum boleh ditetapkan sebagai alias untuk panggilan cepat. Kaedah ini mudah dan praktikal, sesuai untuk keperluan tontonan IP dalam senario yang berbeza.

Untuk membolehkan bekas PHP menyokong pembinaan automatik, terasnya terletak pada mengkonfigurasi proses integrasi berterusan (CI). 1. Gunakan Dockerfile untuk menentukan persekitaran PHP, termasuk imej asas, pemasangan lanjutan, pengurusan ketergantungan dan tetapan kebenaran; 2. Konfigurasi alat CI/CD seperti Gitlabci, dan tentukan peringkat binaan, ujian dan penempatan melalui fail .gitlab-ci.yml untuk mencapai pembinaan, pengujian dan penggunaan automatik; 3. Mengintegrasikan kerangka ujian seperti PHPUnit untuk memastikan ujian secara automatik dijalankan selepas perubahan kod; 4. Gunakan strategi penempatan automatik seperti Kubernet untuk menentukan konfigurasi penempatan melalui fail penyebaran.yaml; 5. Mengoptimumkan Dockerfile dan mengamalkan pembinaan pelbagai peringkat

LinuxcanrunonmodesthardwareWithSpecificMinimumRequirements.a1ghzprocessor (x86orx86_64) disediakan, withadual-corecpurecommended.r Amshouldbeatleast512mbforcommand-lineuseor2gbfordesktopenvironments.diskspacerequiresaminimumof5-10gb, walaupun25gbisbetterforad

Sebagai perintis di dunia digital, nama kod unik Bitcoin dan teknologi asas selalu menjadi tumpuan perhatian orang. Kod standardnya adalah BTC, juga dikenali sebagai XBT pada platform tertentu yang memenuhi piawaian antarabangsa. Dari sudut pandangan teknikal, Bitcoin bukanlah satu gaya kod tunggal, tetapi projek perisian sumber terbuka yang besar dan canggih. Kod terasnya terutamanya ditulis dalam C dan menggabungkan kriptografi, sistem yang diedarkan dan prinsip ekonomi, supaya sesiapa sahaja dapat melihat, mengkaji dan menyumbang kodnya.

Perintah penutupan Linux/macOS boleh ditutup, dimulakan semula, dan operasi masa melalui parameter. 1. Matikan mesin dengan serta -merta dan gunakan parameter sudoshutdownnow atau -H/-p; 2. Gunakan titik masa atau masa tertentu untuk penutupan, batalkan penggunaan -c; 3. Gunakan parameter -r untuk memulakan semula, menyokong permulaan semula; 4. Perhatikan keperluan untuk kebenaran sudo, berhati -hati dalam operasi jauh, dan elakkan kehilangan data.

Membina persekitaran kontena tugas PHP yang bebas boleh dilaksanakan melalui Docker. Langkah -langkah khusus adalah seperti berikut: 1. Pasang Docker dan DockerCompose sebagai asas; 2. Buat direktori bebas untuk menyimpan fail Dockerfile dan Crontab; 3. Tulis Dockerfile untuk menentukan persekitaran PHPCLI dan memasang cron dan sambungan yang diperlukan; 4. Tulis fail crontab untuk menentukan tugas masa; 5. Tulis direktori script-compose.yml mount dan konfigurasikan pembolehubah persekitaran; 6. Mulakan bekas dan sahkan log. Berbanding dengan melaksanakan tugas masa dalam bekas web, bekas bebas mempunyai kelebihan pengasingan sumber, persekitaran murni, kestabilan yang kuat, dan pengembangan yang mudah. Untuk memastikan penangkapan dan penangkapan ralat

Sahkan nama peranti cakera keras sasaran (seperti /dev /sda) untuk mengelakkan secara tidak sengaja memadam cakera sistem; 2. Gunakan sudoddif =/dev/sifar =/dev/sdxbs = 1mstatus = kemajuan untuk menimpa nilai sifar dalam cakera penuh, yang sesuai untuk kebanyakan senario; 3. Gunakan sudoshred-v-n3/dev/sdx untuk tiga data rawak overwrites untuk memastikan ia tidak dapat dipulihkan; 4. Secara pilihan melaksanakan Sudobadblocks-WSV/Dev/SDX untuk ujian menulis yang merosakkan; Akhirnya gunakan sudohexdump-c/dev/sdx | kepala untuk mengesahkan sama ada semuanya sifar dan melengkapkan selamat.
