2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
सूत्रं प्रक्रियायां निष्पादन-एककं भवति ।
वर्तमानप्रक्रियायां कार्यक्रमानां निष्पादनस्य उत्तरदायी,
एकस्मिन् प्रक्रियायां न्यूनातिन्यूनम् एकः सूत्रः भवति
एकस्मिन् प्रक्रियायां बहुविधसूत्राणि भवितुम् अर्हन्ति
अनेकाः सूत्राः एकस्यामेव प्रक्रियायाः सर्वाणि संसाधनानि साझां कुर्वन्ति, प्रत्येकं सूत्रं च प्रचालनतन्त्रस्य एकीकृतनिर्धारणे भागं गृह्णाति
इदं केवलं प्रक्रिया = स्मृतिसंसाधनम् + मुख्यसूत्रम् + बालसूत्रम् +... इति अवगन्तुं शक्यते।
निकटसम्बद्धानां कार्याणां कृते समवर्तीकाले बहुसूत्रीकरणं प्राधान्यं भवति येषु कार्येषु निकटसम्बन्धः नास्ति तथा च तुल्यकालिकरूपेण स्वतन्त्रः भवति, तेषां कृते बहुप्रक्रियायाः चयनं अनुशंसितम्
सूत्राणां प्रक्रियाणां च भेदः : १.
Linux प्रणाल्यां प्रक्रियां द्रष्टुं बहवः आदेशाः सन्ति, यथा pidstat, top, ps, प्रक्रियां द्रष्टुं शक्नुवन्ति, a अपि द्रष्टुं शक्नुवन्ति
प्रक्रियायाः अन्तर्गतं सूत्रम्
ubuntu इत्यस्य अधः sysstat tool इत्यस्य संस्थापनस्य आवश्यकतायाः अनन्तरं pidstat इत्यस्य समर्थनं कर्तुं शक्यते ।
sudo apt sysstat संस्थापयन्तु
विकल्पाः
-t: निर्दिष्टप्रक्रियायाः सह सम्बद्धानि सूत्राणि प्रदर्शयन्तु
-p: प्रक्रिया pid निर्दिशतु
उदाहरण
प्रक्रिया 12345 इत्यनेन सह सम्बद्धानि सूत्राणि पश्यन्तु
सुदो पिडस्तत् -त -प 12345
सर्वैः प्रक्रियाभिः सह सम्बद्धानि सूत्राणि पश्यन्तु
सुदो पिदस्तत् -त
प्रक्रिया 12345 इत्यनेन सह सम्बद्धानि धागानि पश्यन्तु, प्रत्येकं 1 सेकण्ड् मध्ये आउटपुट्
सुदो पिडस्तत् -त -प 12345 1
सर्वैः प्रक्रियाभिः सह सम्बद्धानि सूत्राणि पश्यन्तु, प्रत्येकं १ सेकेण्ड् मध्ये आउटपुट् कुर्वन्तु
सुदो पिदस्तत् -t 1
कस्यचित् प्रक्रियायाः अन्तर्गतं थ्रेड् द्रष्टुं top आदेशस्य उपयोगं कुर्वन्तु pid निर्दिष्टुं -p इत्यनेन सह संयोजनेन -H विकल्पस्य उपयोगः करणीयः ।
विकल्पाः
-H: सूत्रसूचना प्रदर्शयन्तु
-p: प्रक्रिया pid निर्दिशतु
उदाहरण
प्रक्रिया 12345 इत्यनेन सह सम्बद्धानि सूत्राणि पश्यन्तु
सुदो शीर्ष -H -p 12345
सर्वैः प्रक्रियाभिः सह सम्बद्धानि सूत्राणि पश्यन्तु
सुदो शीर्ष -H
प्रक्रियायाः अन्तर्गतं सर्वान् थ्रेड् द्रष्टुं -T विकल्पेन सह संयुक्तं ps आदेशस्य उपयोगं कुर्वन्तु
विकल्पाः
-T: सूत्रसूचना प्रदर्शयन्तु
-p: प्रक्रिया pid निर्दिशतु
उदाहरण
प्रक्रिया 12345 इत्यनेन सह सम्बद्धानि सूत्राणि पश्यन्तु
सुदो प्स -त -प 12345
सर्वैः प्रक्रियाभिः सह सम्बद्धानि सूत्राणि पश्यन्तु
सुदो प्स -T
बहुप्रक्रियाविधाने प्रत्येकं प्रक्रिया परस्परं बाधां विना भिन्नानां कार्याणां उत्तरदायी भवति ।
बहु-सूत्र-विधाने प्रक्रियायां बहु-सूत्राणि भवितुम् अर्हन्ति, समान-स्मृति-स्थानं साझां कुर्वन्ति, सूत्राणि च प्रत्यक्षतया संवादं कर्तुं शक्नुवन्ति ।
pthread_create() इत्यस्य उपयोगः थ्रेड् निर्मातुं भवति ।
pthread_create() इत्यस्य सफलतया आह्वानानन्तरं 0 प्रत्यागमिष्यति, अन्यथा त्रुटिसङ्केतं प्रत्यागमिष्यति ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
पैरामीटर् विवरणम् : १.
return value: 1.1.
सूचना:
// todo : 创建一个线程,并在线程中打印出“Hello, World!”
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
// 线程函数
//@param arg 线程函数参数
void * print_hello(void *arg) {
printf("%sn",(char *)arg);
}
int main() {
pthread_t tid; //? typedef unsigned long int pthread_t;
// 创建线程
//@param tid 线程ID
//@param attr 线程属性
//@param start_routine 线程函数
//@param arg 线程函数参数
int ret = pthread_create(&tid, NULL,print_hello, "Hello, World!");
if (ret!= 0){
printf("pthread_create error!n");
return 1;
}
sleep(1); // 等待线程执行完毕
return 0;
}
pthread_exit() इत्यस्य उपयोगः थ्रेड् इत्यस्मात् निर्गन्तुं भवति ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
void pthread_exit(void *retval);
पैरामीटर् विवरणम् : १.
pthread_join() इत्यस्य उपयोगः थ्रेड् समाप्तिं प्रतीक्षितुं भवति,
pthread_join() इति आह्वानं कृत्वा, वर्तमानं थ्रेड् यावत् थ्रेड् समाप्तं न भवति तावत् अवरुद्धं भविष्यति ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
पैरामीटर् विवरणम् : १.
return value: 1.1.
// todo : 创建一个线程,并在线程中打印出“Hello, World!”
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
// 线程函数
//@param arg 线程函数参数
void * print_hello(void *arg) {
sleep(1); // 休眠1秒
printf("%sn",(char *)arg);
pthread_exit(NULL); // 线程退出
}
int main() {
pthread_t tid; //? typedef unsigned long int pthread_t;
// 创建线程
//* @param tid 线程ID
//* @param attr 线程属性
//* @param start_routine 线程函数
//* @param arg 线程函数参数
int ret = pthread_create(&tid, NULL,print_hello, "Hello, World!");
if (ret!= 0){
printf("pthread_create error!n");
return 1;
}
printf("等待线程结束...n");
// 等待线程结束
//* @param thread 线程ID
//* @param status 线程退出状态
pthread_join(tid, NULL);
return 0;
}
等待线程结束...
Hello, World!
सूत्राणि संयोजनीयानि विच्छेदनीयानि च इति विभक्ताः भवन्ति
// todo : 创建一个线程,并在线程中打印出“Hello, World!”
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
// 线程函数
//@param arg 线程函数参数
void * print_hello(void *arg) {
sleep(1); // 休眠1秒
printf("%sn",(char *)arg);
pthread_exit(NULL); // 线程退出
}
int main() {
pthread_t tid; //? typedef unsigned long int pthread_t;
// 创建线程
//* @param tid 线程ID
//* @param attr 线程属性
//* @param start_routine 线程函数
//* @param arg 线程函数参数
int ret = pthread_create(&tid, NULL,print_hello, "Hello, World!");
if (ret!= 0){
printf("pthread_create error!n");
return 1;
}
printf("等待线程结束...n");
// 等待线程结束
//* @param thread 线程ID
//* @param status 线程退出状态
//pthread_join(tid, NULL);//! 阻塞等待线程结束,直到线程结束后才继续往下执行
//线程分离
pthread_detach(tid); //! 分离线程,不用等待线程结束后才退出程序,该线程的资源在它终止时由系统来释放。
printf("主线程结束n");
return 0;
}
// todo : 创建多个线程,执行不同的任务
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
// 线程函数
//@param arg 线程函数参数
void * print_hello_A(void *arg) {
sleep(1); // 休眠1秒
printf("%sn",(char *)arg);
pthread_exit(NULL); // 线程退出
}
// 线程函数
//@param arg 线程函数参数
void * print_hello_B(void *arg) {
sleep(2); // 休眠2秒
printf("%sn",(char *)arg);
pthread_exit(NULL); // 线程退出
}
int main() {
pthread_t tidA; //? 存储线程ID typedef unsigned long int pthread_t;
pthread_t tidB;
// 创建线程
//* @param tid 线程ID
//* @param attr 线程属性
//* @param start_routine 线程函数
//* @param arg 线程函数参数
int retA = pthread_create(&tidA, NULL,print_hello_A, "A_ Hello, World!");
if (retA!= 0){
printf("pthread_create error!n");
return 1;
}
int retB = pthread_create(&tidB, NULL,print_hello_B, "B_ Hello, World!");
if (retB!= 0){
printf("pthread_create error!n");
return 1;
}
printf("等待线程结束...n");
// 等待线程结束
//* @param thread 线程ID
//* @param status 线程退出状态
pthread_join(tidA, NULL);//! 阻塞等待线程结束,直到线程结束后才继续往下执行
pthread_join(tidB, NULL);
printf("主线程结束n");
return 0;
}
// todo : 创建多个线程,执行相同任务
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
//? 两个线程执行相同任务,对函数中的值修改了,会不会影响到其他线程的执行?
//! 在多线程编程中,如果多个线程执行相同的任务并且对共享资源进行修改,可能会影响到其他线程的执行。
//! 这是因为多个线程共享相同的内存空间,对共享资源的修改可能会导致竞态条件(race condition),
//! 从而导致不可预测的行为。
//! print_hello函数中的变量i是局部变量,每个线程都会有自己的i副本,因此对i的修改不会影响到其他线程。
//! 但是,如果涉及到共享资源(例如全局变量或静态变量),就需要考虑线程同步的问题,以避免竞态条件。
//*局部变量:每个线程都有自己的栈空间,因此局部变量是线程私有的,不会影响到其他线程。
//*共享资源:如果多个线程访问和修改同一个全局变量或静态变量,就需要使用同步机制(如互斥锁、信号量等)来确保线程安全。
//Linux:在Linux系统中,默认的线程栈大小通常是8MB。可以使用ulimit -s命令查看和修改当前用户的线程栈大小。例如,ulimit -s 1024将线程栈大小设置为1MB。
//Windows:在Windows系统中,默认的线程栈大小是1MB。可以通过编译器选项或在创建线程时指定栈大小来修改。
// 线程函数
//@param arg 线程函数参数
void * print_hello(void *arg) {
for (char i = 'a'; i < 'z' ; ++i) {
printf("%cn", i);
sleep(1); // 休眠1秒
}
pthread_exit(NULL); // 线程退出
}
int main() {
pthread_t tid[2]={0}; //? 存储线程ID的数组 typedef unsigned long int pthread_t;
for (int i = 0; i < 2; ++i) {
// 创建线程
//* @param tid 线程ID
//* @param attr 线程属性
//* @param start_routine 线程函数
//* @param arg 线程函数参数
int retA = pthread_create(&tid[i], NULL,print_hello, NULL);
if (retA!= 0){
printf("pthread_create error!n");
return 1;
}
}
printf("等待线程结束...n");
// 等待线程结束
//* @param thread 线程ID
//* @param status 线程退出状态
pthread_join(tid[0], NULL);//! 阻塞等待线程结束,直到线程结束后才继续往下执行
pthread_join(tid[1], NULL);
printf("主线程结束n");
return 0;
}
प्रक्रियाणां मध्ये अन्यः संचारः सूत्राणां मध्ये संचारस्य अपि प्रवर्तते ।
pthread_create() फंक्शन् इत्यस्य माध्यमेन चाइल्ड् थ्रेड् रचयन्ते सति, pthread_create() इत्यस्य चतुर्थः पैरामीटर् बाल थ्रेड् इत्यस्य फंक्शन् इत्यस्मै पारितः पैरामीटर् भवति ।
pthread_exit() फंक्शन् मार्गेण बालसूत्रात् निर्गच्छन्ति चेत्, भवान् मुख्यसूत्रे पैरामीटर्स् पारयितुं शक्नोति ।
void pth_exit(void *retval);
pthread_join() फंक्शन् इत्यस्य माध्यमेन उप-थ्रेड् इत्यस्य अन्तं प्रतीक्षमाणे उप-थ्रेड् इत्यस्य रिटर्न् पैरामीटर्स् प्राप्नुवन्तु ।
int pthread_join (pthread_t __th, void **__thread_return);
//二级指针获取到了pthread_exit()函数参数指针的指向地址,通过该地址可以获取到子线程的返回参数。
// todo : 线程直接通讯,子线程向父线程传参
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
// 线程函数
//@param arg 线程函数参数
void * print_hello(void *arg) {
printf("子线程开始,结束之时传递参数100的地址n");
sleep(1); // 休眠1秒
//! int num=100;//局部变量,函数结束释放内存
static int num=100;//* 静态局部变量,函数结束不释放内存,延长生命周期
pthread_exit(&num); // 线程退出
}
int main() {
pthread_t tid; //? 存储线程ID typedef unsigned long int pthread_t;
// 创建线程
//* @param tid 线程ID
//* @param attr 线程属性
//* @param start_routine 线程函数
//* @param arg 线程函数参数
int retA = pthread_create(&tid, NULL,print_hello, NULL);
if (retA!= 0){
printf("pthread_create error!n");
return 1;
}
printf("等待线程结束...n");
void* num;//获取子进程传递的参数,num指向了子进程传递的参数
// 等待线程结束
//* @param thread 线程ID
//* @param status 线程退出状态
pthread_join(tid, (void **)&num);//! 阻塞等待线程结束,直到线程结束后才继续往下执行
printf("子线程结束,传递的参数为%dn",*(int*)num);
printf("主线程结束n");
return 0;
}
Mutex इति समन्वयनतन्त्रं यस्य उपयोगः साझासंसाधनानाम् अभिगमनं नियन्त्रयितुं भवति ।
थ्रेड् इत्यस्य मुख्यं लाभं वैश्विकचरद्वारा सूचनां साझां कर्तुं क्षमता अस्ति, परन्तु एतत् सुविधाजनकं साझेदारी मूल्येन आगच्छति:
अनेकाः सूत्राः एकस्मिन् समये एकमेव चरं न परिवर्तयन्ति इति सुनिश्चितं कर्तव्यम्
अन्यैः सूत्रैः परिवर्तिताः चराः सूत्रं न पठति वस्तुतः द्वौ सूत्रौ एकस्मिन् समये महत्त्वपूर्णविभागं प्राप्तुं न शक्नुवन्ति ।
म्यूटेक्स-लॉक् इत्यस्य सिद्धान्तः अस्ति यत् यदा कश्चन थ्रेड् म्यूटेक्स् क्षेत्रे प्रवेशं कर्तुं प्रयतते तदा यदि म्यूटेक्स् क्षेत्रं पूर्वमेव अन्यैः थ्रेड् इत्यनेन आक्रान्तः अस्ति तर्हि म्यूटेक्स् क्षेत्रं मुक्तं न भवति तावत् थ्रेड् अवरुद्धः भविष्यति
इदं मूलतः pthread_mutex_t प्रकारस्य चरः अस्ति, यस्मिन् mutex क्षेत्रस्य स्थितिं प्रतिनिधितुं पूर्णाङ्कमूल्यं भवति ।
यदा मूल्यं 1 भवति तदा तस्य अर्थः अस्ति यत् वर्तमानः महत्त्वपूर्णः संसाधनः अभिगमनार्थं स्पर्धां कर्तुं शक्नोति, तथा च यः सूत्रः म्यूटेक्स् तालं प्राप्नोति सः महत्त्वपूर्णविभागे प्रवेशं कर्तुं शक्नोति । अस्मिन् समये मूल्यं 0 अस्ति अन्ये सूत्राणि केवलं प्रतीक्षितुं शक्नुवन्ति ।
यदा मूल्यं 0 भवति तदा तस्य अर्थः अस्ति यत् वर्तमानः महत्त्वपूर्णः संसाधनः अन्यैः सूत्रैः आक्रान्तः अस्ति तथा च महत्त्वपूर्णविभागे प्रवेशं कर्तुं न शक्नोति तथा च केवलं प्रतीक्षां कर्तुं शक्नोति ।
typedef union
{
struct __pthread_mutex_s __data; // 互斥锁的结构体
char __size[__SIZEOF_PTHREAD_MUTEX_T];// 互斥锁的大小
long int __align;// 互斥锁的对齐
} pthread_mutex_t;
थ्रेड् म्यूटेक्स् लॉक् इत्यस्य आरम्भस्य मुख्यौ उपायौ स्तः ।
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER
गतिशीलप्रारम्भः गतिशीलप्रारम्भीकरणे मुख्यतया द्वौ कार्यौ भवतः: pthread_mutex_init फंक्शन् तथा pthread_mutex_destroy फंक्शन् च
म्यूटेक्स-लॉक् इत्यस्य आरम्भार्थं उपयुज्यते, एतत् द्वौ पैरामीटर् स्वीकुर्वति: म्यूटेक्स-लॉक् इत्यस्य पता, म्यूटेक्स-लॉक् इत्यस्य विशेषताः च ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
पैरामीटर् विवरणम् : १.
return value: 1.1.
mutex lock इत्यस्य नाशार्थं प्रयुक्तः, एतत् एकं पैरामीटर् स्वीकुर्वति: mutex lock इत्यस्य पता ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
पैरामीटर् विवरणम् : १.
return value: 1.1.
उदाहरण:
// todo : 互斥锁;创建两个线程,分别对全局变量进⾏ +1 操作
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
static int global = 0;// 全局变量
//静态初始化互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;// 互斥锁
//动态初始化互斥锁
pthread_mutex_t mut;// 互斥锁
// 线程函数
//@param arg 线程函数参数
void * print_hello(void *arg) {
printf("子线程开始n");
int loops = *(int *)arg;
int i,tmp = 0;
for (i = 0;i < loops;i++){
pthread_mutex_lock(&mut);// 加锁
printf("子线程%d,global=%dn",i,global);
tmp = global;
tmp++;
global = tmp;
pthread_mutex_unlock(&mut);// 解锁
}
printf("子线程结束n");
pthread_exit(NULL); // 线程退出
}
int main() {
// 动态初始化互斥锁
//* @param mutex 互斥锁
//* @param attr 互斥锁属性 NULL 是默认属性
int r= pthread_mutex_init(&mut,NULL);
if (r!= 0){
printf("pthread_mutex_init error!n");
return 1;
}
pthread_t tid[2]={0}; //? 存储线程ID typedef unsigned long int pthread_t;
int arg=20;
for (int i = 0; i < 2; i++){
// 创建线程
//* @param tid 线程ID
//* @param attr 线程属性
//* @param start_routine 线程函数
//* @param arg 线程函数参数
int retA = pthread_create(&tid[i], NULL,print_hello, &arg);
if (retA!= 0){
printf("pthread_create error!n");
return 1;
}
}
printf("等待线程结束...n");
// 等待线程结束
//* @param thread 线程ID
//* @param status 线程退出状态
pthread_join(tid[0],NULL );//! 阻塞等待线程结束,直到线程结束后才继续往下执行
pthread_join(tid[1],NULL );
printf("%dn",global);
printf("主线程结束n");
// 销毁动态创建的互斥锁
//* @param mutex 互斥锁
pthread_mutex_destroy(&mut);// 销毁互斥锁
return 0;
}
धागा समन्वयनम् : परस्परं बहिष्कारस्य आधारेण (अधिकांशेषु सन्दर्भेषु) अन्यतन्त्रैः आगन्तुकानां संसाधनानाम् क्रमेण प्रवेशं निर्दिशति ।
कण्डिशन् वेरिएबल : थ्रेड् लाइब्रेरी द्वारा विशेषतया थ्रेड् समन्वयनार्थं प्रदत्तं तन्त्रम् ।
सूत्रसमन्वयनार्थं एकः विशिष्टः अनुप्रयोगपरिदृश्यः उत्पादकानां उपभोक्तृणां च मध्ये भवति ।
अस्मिन् प्रतिरूपे उत्पादकसूत्रे उपभोक्तृसूत्रे च विभक्तं भवति, अनेकसूत्राणां समन्वयनप्रक्रिया अस्मिन् सूत्रेण अनुकरणं भवति
अस्मिन् प्रतिरूपे निम्नलिखितघटकाः आवश्यकाः सन्ति ।
- गोदामः उत्पादानाम् संग्रहणार्थं प्रयुक्तः, सामान्यतया साझासंसाधनरूपेण
- उत्पादकसूत्रः उत्पादानाम् उत्पादनार्थं प्रयुक्तः
- उपभोक्तृसूत्रः उत्पादानाम् उपभोगार्थं प्रयुक्तः
सिद्धान्तः १.
यदा गोदामे उत्पादः नास्ति तदा उपभोक्तृसूत्रस्य उपभोगं कर्तुं पूर्वं यावत् उत्पादः नास्ति तावत् प्रतीक्षितव्यम् ।
यदा गोदामः उत्पादैः पूरितः भवति तदा उत्पादकसूत्रस्य प्रतीक्षा भवति यावत् उपभोक्तृसूत्रः उत्पादानाम् उपभोगं न करोति ।
मुख्यसूत्रः उपभोक्ता अस्ति
न उपसूत्राणि उत्पादकत्वेन
// todo : 基于互斥锁实现⽣产者与消费者模型主线程为消费者,n 个⼦线程作为⽣产者
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
static int n = 0; // 产品数量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;// 互斥锁
//生产者执行函数
void * dofunc(void *arg) {
int arg1 = *(int*)arg;
for (int i = 0; i <arg1; i++) {
//获取互斥锁
pthread_mutex_lock(&mutex);
//生产产品
printf("生产者%ld生产了%d个产品n",pthread_self(),++n);//! pthread_self()返回当前线程ID
//释放互斥锁
pthread_mutex_unlock(&mutex);
//休眠1秒
sleep(1);
}
pthread_exit(NULL);
}
int main() {
pthread_t tid[4]={0}; //? 存储线程ID typedef unsigned long int pthread_t;
int arr[4]={1,2,3,4};
for (int i = 0; i < 4; i++) {
// 创建线程
//* @param tid 线程ID
//* @param attr 线程属性
//* @param start_routine 线程函数
//* @param arg 线程函数参数
int retA = pthread_create(&tid[i], NULL,dofunc,&arr[i] );
if (retA!= 0){
printf("pthread_create error!n");
return 1;
}
}
//消费者执行
for (int i = 0;i<10;i++) {
//获取互斥锁
pthread_mutex_lock(&mutex);
while (n > 0){
//消费产品
printf("消费者%ld消费了1个产品:%dn",pthread_self(),n--);
}
//释放互斥锁
pthread_mutex_unlock(&mutex);
//休眠1秒
sleep(1);
}
printf("等待线程结束...n");
// 等待线程结束
//* @param thread 线程ID
//* @param status 线程退出状态
pthread_join(tid[0],NULL );//! 阻塞等待线程结束,直到线程结束后才继续往下执行
pthread_join(tid[1],NULL );
pthread_join(tid[2],NULL );
pthread_join(tid[3],NULL );
return 0;
}
कण्डिशन् वेरिएबल इति समन्वयनतन्त्रं यत् थ्रेड् इत्यस्य निरन्तरं चालनपूर्वं निश्चितं कण्डिशन् पूरयितुं प्रतीक्षां कर्तुं शक्नोति ।
कण्डिशन् वेरियेबल् इत्यस्य सिद्धान्तः अस्ति यत् तस्मिन् म्यूटेक्स् लॉक्, प्रतीक्षमाणा कतारं च भवति ।
प्रतीक्षमाणानां कतारानाम्, कण्डिशन् चरानाम् रक्षणार्थं म्यूटेक्स् लॉक् इत्यस्य उपयोगः भवति ।
कण्डिशन् चरस्य प्रकृतिः pthread_cond_t प्रकारः अस्ति
其他线程可以阻塞在这个条件变量上, 或者唤
醒阻塞在这个条件变量上的线程
typedef union
{
struct __pthread_cond_s __data;
char __size[__SIZEOF_PTHREAD_COND_T];
__extension__ long long int __align;
} pthread_cond_t;
कण्डिशन् चरानाम् आरम्भीकरणं स्थिरप्रारम्भीकरणं गतिशीलप्रारम्भीकरणं च इति विभक्तं भवति ।
स्थिररूपेण आरम्भितानां कण्डिशन् चरानाम् कृते, भवद्भिः प्रथमं pthread_cond_t प्रकारस्य चरं परिभाषितव्यं, ततः PTHREAD_COND_INITIALIZER इत्यत्र आरभणीयम् ।
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
गतिशीलरूपेण कण्डिशन् चरस्य आरम्भार्थं प्रथमं pthread_cond_t प्रकारस्य चरं परिभाषितुं आवश्यकं, ततः तस्य आरम्भार्थं pthread_cond_init फंक्शन् आह्वयितुं आवश्यकम् ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
पैरामीटर् विवरणम् : १.
return value: 1.1.
कण्डिशन् चरस्य नाशार्थं उपयुज्यते, एतत् एकं पैरामीटर् स्वीकुर्वति: कण्डिशन् चरस्य पता ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
पैरामीटर् विवरणम् : १.
return value: 1.1.
कण्डिशन् वेरियेबल् इत्यस्य उपयोगः प्रतीक्षा, सूचना च इति विभक्तः अस्ति
प्रतीक्षाकार्यं pthread_cond_wait() त्रयः पैरामीटर्स् स्वीकुर्वति: कण्डिशन् चरस्य पता, म्यूटेक्स् लॉकस्य पता, प्रतीक्षासमयः च ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
पैरामीटर् विवरणम् : १.
return value: 1.1.
सूचना कार्य
pthread_cond_signal() एकं पैरामीटर् स्वीकुर्वति: कण्डिशन् चरस्य पता ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
पैरामीटर् विवरणम् : १.
return value: 1.1.
सर्वाणि कार्याणि सूचयन्तु
pthread_cond_broadcast() एकं पैरामीटर् स्वीकुर्वति: कण्डिशन् चरस्य पता ।
कार्यशीर्षकसञ्चिका : १.
#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cond);
पैरामीटर् विवरणम् : १.
return value: 1.1.
step 1 : 消费者线程判断消费条件是否满足 (仓库是否有产品),如果有产品可以消费,则可以正
常消费产品,然后解锁
step 2 : 当条件不能满足时 (仓库产品数量为 0),则调用 pthread_cond_wait 函数, 这个函数
具体做的事情如下:
在线程睡眠之前,对互斥锁解锁
让线程进⼊到睡眠状态
等待条件变量收到信号时 唤醒,该函数重新竞争锁,并获取锁后,函数返回
step 3 :重新判断条件是否满足, 如果不满足,则继续调用 pthread_cond_wait 函数
step 4 : 唤醒后,从 pthread_cond_wait 返回,消费条件满足,则正常消费产品
step 5 : 释放锁,整个过程结束
म्यूटेक्स-लॉक्-सहितं कण्डिशन्-चरानाम् उपयोगः किमर्थं आवश्यकः ?
साझादत्तांशस्य रक्षणं कुर्वन्तु : १.
साझादत्तांशस्य रक्षणार्थं तथा च केवलं एकः सूत्रः एकस्मिन् समये दत्तांशं अभिगन्तुं परिवर्तयितुं च शक्नोति इति सुनिश्चित्य Mutex तालानां उपयोगः भवति ।
एतेन दत्तांशजातिः, असङ्गतिः च परिहृता भवति ।
अन्यसूत्राणां कृते कश्चन कण्डिशन् पूरितः इति सूचयितुं थ्रेड्-मध्ये संचारार्थं कण्डिशन्-चरानाम् उपयोगः भवति ।
परन्तु कण्डिशन् वेरबल् इत्यस्य संचालनं स्वयमेव साझादत्तांशस्य रक्षणं न ददाति अतः म्यूटेक्स् लॉक् इत्यनेन सह संयोजनेन तस्य उपयोगः आवश्यकः ।
मिथ्या जागरणं परिहरन्तु : १.
शर्तचरानाम् एकं लक्षणं अस्ति यत् मिथ्या जागरणं भवितुम् अर्हति ।
स्पष्टं सूचनां विना सूत्रं जागर्यते इत्यर्थः । अस्याः परिस्थित्याः कारणेन अशुद्धक्रियाः परिहरितुं
सूत्रेण पुनः परीक्षणं करणीयम् यत् जागरणानन्तरं शर्तः वास्तवतः पूरिता अस्ति वा इति ।
म्यूटेक्सस्य उपयोगेन सुनिश्चितं भवति यत् परिस्थितिपरीक्षायां साझादत्तांशः अन्यैः सूत्रैः परिवर्तितः न भवति, अतः मिथ्याजागरणजन्यदोषाः परिहृताः भवन्ति ।
सूचना सम्यक् अस्ति इति सुनिश्चितं कुर्वन्तु:
यदा कश्चन थ्रेड् अन्यथ्रेड्-आन् कण्डिशन्-चर-माध्यमेन सूचयति तदा तस्य सूचनां दातुं पूर्वं साझा-दत्तांशः अद्यतनः अभवत् इति सुनिश्चितं कर्तव्यम् ।
एकः म्यूटेक्सः एतस्य गारण्टीं ददाति, यत् सुनिश्चितं करोति यत् सर्वाणि दत्तांश-अद्यतन-कार्यक्रमाः तालान् मुक्तुं पूर्वं सम्पन्नाः सन्ति ।
तथैव सूचनां प्राप्य सूत्रेण कण्डिशन् परीक्षितुं पूर्वं म्यूटेक्स् धारयितुं आवश्यकं भवति यत् कण्डिशन् परीक्षिते सति दत्तांशः स्थिरः भवति इति सुनिश्चितं भवति
जटिल समन्वयनप्रतिमानं कार्यान्वितम् : १.
म्यूटेक्स-लॉक्-इत्यस्य कण्डिशन्-चर-सहितं संयोजनेन अधिकजटिल-समन्वयन-प्रतिमानं कार्यान्वितुं शक्यते, यथा उत्पादक-उपभोक्तृ-समस्याः, पाठक-लेखक-समस्याः इत्यादयः म्यूटेक्स् साझादत्तांशस्य रक्षणं करोति, तथा च थ्रेड्-मध्ये समन्वयस्य संचारस्य च कृते कण्डिशन्-चरानाम् उपयोगः भवति ।
// todo : 条件变量
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
static int number = 0;// 产品数量
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;// 互斥锁
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;// 条件变量
// 线程函数
//@param arg 线程函数参数
void * thread_handler(void *arg) {
int cnt = atoi((char *)arg);// 获取线程参数
int i,tmp;// 临时变量
for(i = 0;i < cnt;i++){// 生产产品
pthread_mutex_lock(&mtx);// 上锁
printf("线程 [%ld] ⽣产⼀个产品,产品数量为:%dn",pthread_self(),++number);
pthread_mutex_unlock(&mtx);// 解锁
//! 唤醒cond阻塞的线程
//! @param cond 条件变量
//pthread_cond_signal(&cond);//! 只能唤醒一个线程,如果有多个线程在等待,则只有一个线程会被唤醒
//唤醒所有线程
pthread_cond_broadcast(&cond);
}
pthread_exit((void *)0);// 线程退出
}
int main(int argc,char *argv[]) {
pthread_t tid[argc-1];// 线程ID
int i;
int err;
int total_of_produce = 0;// 总共生产的产品数量
int total_of_consume = 0;// 总共消费的产品数量
bool done = false;// 是否完成生产
//循环创建线程
for (i = 1;i < argc;i++){
total_of_produce += atoi(argv[i]);// 计算总共需要生产的产品数量
// 创建线程
err = pthread_create(&tid[i-1],NULL,thread_handler,(void *)argv[i]);
if (err != 0){
perror("[ERROR] pthread_create(): ");
exit(EXIT_FAILURE);
}
}
//消费者
for (;;){
//*先获取锁,再进行条件变量的等待
pthread_mutex_lock(&mtx);// 上锁
//*while循环来判断条件,避免虚假唤醒
while(number == 0) {// 等待生产者生产产品
//! 等待条件变量
//! @param cond 条件变量
//! @param mtx 互斥锁
//! 函数中会释放互斥锁,并阻塞线程,
//! 直到条件变量被唤醒,再重新竞争互斥锁,获取互斥锁并继续执行
pthread_cond_wait(&cond, &mtx);
}
while(number > 0){
total_of_consume++;// 总共消费的产品数量
printf("消费⼀个产品,产品数量为:%dn",--number);// 消费产品
done = total_of_consume >= total_of_produce;// 是否完成生产
}
pthread_mutex_unlock(&mtx);// 解锁
if (done)// 是否完成生产
break;
}
// 等待线程退出
for(i = 0;i < argc-1;i++){
pthread_join(tid[i],NULL);
}
return 0;
}
//循环创建线程
for (i = 1;i < argc;i++){
total_of_produce += atoi(argv[i]);// 计算总共需要生产的产品数量
// 创建线程
err = pthread_create(&tid[i-1],NULL,thread_handler,(void *)argv[i]);
if (err != 0){
perror("[ERROR] pthread_create(): ");
exit(EXIT_FAILURE);
}
}
//消费者
for (;;){
//*先获取锁,再进行条件变量的等待
pthread_mutex_lock(&mtx);// 上锁
//*while循环来判断条件,避免虚假唤醒
while(number == 0) {// 等待生产者生产产品
//! 等待条件变量
//! @param cond 条件变量
//! @param mtx 互斥锁
//! 函数中会释放互斥锁,并阻塞线程,
//! 直到条件变量被唤醒,再重新竞争互斥锁,获取互斥锁并继续执行
pthread_cond_wait(&cond, &mtx);
}
while(number > 0){
total_of_consume++;// 总共消费的产品数量
printf("消费⼀个产品,产品数量为:%dn",--number);// 消费产品
done = total_of_consume >= total_of_produce;// 是否完成生产
}
pthread_mutex_unlock(&mtx);// 解锁
if (done)// 是否完成生产
break;
}
// 等待线程退出
for(i = 0;i < argc-1;i++){
pthread_join(tid[i],NULL);
}
return 0;
}