zoukankan      html  css  js  c++  java
  • Linux操作系统实验-线程同步

    操作系统编程--线程同步问题

    1. 互斥量

    • 互斥量是最简单的线程同步的方法

    • 互斥量(互斥锁),处于两态之一的变量:解锁和加锁

    • 两个状态可以保证资源访问的串行

    • 操作系统直接提供了互斥量的API

    • 开发者可以直接使用API完成资源的加锁、解锁操作

    具体操作

    ◆ pthread_mutex_t //用于定义线程互斥锁对象
    ◆ pthread_mutex_lock(&mutex) //上锁操作
    ◆ pthread_mutex_unlock(&mutex) //开锁操作

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <vector>
    
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    
    int num = 0;
    
    void *producer(void*){
        int times = 10000000;
        while(times --){ //不加锁操作则会导致出现共享资源不统一问题 即num 最后不为0
            pthread_mutex_lock(&mutex);
            num += 1;
            pthread_mutex_unlock(&mutex);
        }
    }
    
    void *comsumer(void*){
        int times = 10000000;
        while(times --){
            pthread_mutex_lock(&mutex);
            num -= 1;
            pthread_mutex_unlock(&mutex);
        }
    }
    
    
    int main(){
        printf("Start in main function.");
        pthread_t thread1, thread2;
        pthread_create(&thread1, NULL, &producer, NULL);
        pthread_create(&thread2, NULL, &comsumer, NULL);
        pthread_join(thread1, NULL);
        pthread_join(thread2, NULL);
        printf("Print in main function: num = %d
    ", num);
        return 0;
    }
    
    

    编译运行

    g++ Thread_Mutex.cpp -o Thread_Mutex -lpthread //编译 -lpthread用于连接动态库
    ./Thread_Mutex //运行

    2. 自旋锁

    特点:

    • 自旋锁也是一种多线程同步的变量
    • 使用自旋锁的线程会反复检查锁变量是否可用
    • 自旋锁不会让出CPU,是一种忙等待状态
    • 自旋锁避免了进程或线程上下文切换的开销
    • 操作系统内部很多地方使用的是自旋锁
    • 自旋锁不适合在单核CPU使用

    用到的函数和变量

    • pthread_spinlock_t
    • pthread_ spinlock _lock
    • pthread_ spinlock _unlock

    代码实现:

    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
    //临界资源
    int num = 0;
    pthread_spinlock_t spinlock;
    
    //PRODUCER
    void *producer(void *) {
    	int time = 10000000;
    	while (time--) {
    		pthread_spin_lock(&spinlock);
    		num += 1;
    		pthread_spin_unlock(&spinlock);
    	}
    }
    
    //CONSUMER
    void *consumer(void *) {
    
    	int time = 10000000;
    	while(time--) {		
    		pthread_spin_lock(&spinlock);
    		num -= 1;
    		pthread_spin_unlock(&spinlock);
    	}
    }
    
    int main() {
    	printf("Start int main function.
    ");
    	pthread_t thread1, thread2;
    	pthread_spin_init(&spinlock, 0);//初始化后使用
    	pthread_create(&thread1, NULL , &producer, NULL);
    	
    	pthread_create(&thread2, NULL , &consumer, NULL);
    	
    	pthread_join(thread1, NULL);
    	pthread_join(thread2, NULL);
    	printf("The number is %d
    ", num);
    	return 0;
    }
    

    3. 读写锁

    应用场景:

    • 临界资源多读少写
    • 读取的时候并不会改变临界资源的值

    特点:

    • 读写锁是一种特殊的自旋锁
    • 允许多个读者同时访问资源以提高读性能
    • 对于写操作则是互斥的

    涉及到的函数:

    • pthread_rwlock_t
    • pthread_rwlock_rdlock(读锁)
    • pthread_rwlock_wrlock(写锁)

    代码实现:

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
    //临界资源
    int num = 0;
    
    //Writer
    pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
    void *writer(void *) {
    	int time = 100000;
    	while (time --) {
    		
    			pthread_rwlock_wrlock(&rwlock);//when need to do write operation lock it. forbid other write or read operation.
    
    			num += 1;
    
    			pthread_rwlock_unlock(&rwlock);//unlock it when done.
    		
    	}
    }
    
    //Reader
    void *reader(void *) {
    	int time = 100000;
    	while(time--) {
    		if (time % 1000 == 0) {
    			pthread_rwlock_rdlock(&rwlock);//when need to do write operation lock it. forbid other write or read operation.
    		
    			printf("The number is %d
    ",num);
    
    			pthread_rwlock_unlock(&rwlock);//unlock it when done.
    		}
    
    	}
    }
    
    int main() {
    	printf("Start int main function.
    ");
    	pthread_t thread1, thread2, thread3;
    	
    	pthread_create(&thread1, NULL , &reader, NULL);
    	
    	pthread_create(&thread2, NULL , &reader, NULL);
    
    	pthread_create(&thread3, NULL , &writer, NULL);
    	
    	pthread_join(thread1, NULL);
    	pthread_join(thread2, NULL);
    	pthread_join(thread3, NULL);
    
    	printf("The number is %d
    ", num);
    	return 0;
    }
    
    

    条件变量 -- 缓冲区

    特点:

    • 条件变量是一种相对复杂的线程同步方法
    • 条件变量允许线程睡眠,直到满足某种条件
    • 当满足条件时,可以向该线程信号,通知唤醒

    应用场景:

    • 缓冲区小于等于0时,不允许消费者消费,消费者必须等待
    • 缓冲区满时,不允许生产者往缓冲区生产,生产者必须等待

    使用到的函数

    • pthread_cond_t
    • pthread_cond_wait(等待条件满足)
    • pthread_cond_signal(等待被唤醒)

    代码实现:

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
    //临界资源
    int num = 0;
    int MAX_BUF = 100;//缓冲区
    
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    
    //PRODUCER
    void *producer(void *) {
    	int time = 10000000;
    	while (time--) {
    		pthread_mutex_lock(&mutex);//lock -- mutex
    		
    		while  (num >= MAX_BUF) {
    			pthread_cond_wait(&cond,&mutex); // When run to this, The process change to block status and wait the signal to awake it.
    			printf("This BUf is full.
    ");
    		}
    		num += 1; // num <= MAX_BUF , so produce one product.
    		printf("The current goods number is :%d
    ", num);
    		sleep(1);//produce a product cost one second.
    		pthread_cond_signal(&cond); // send signal.
    		printf("notify the consumer!!
    ");
    
    		pthread_mutex_unlock(&mutex);// unlock -- mutex
    		sleep(1);
    	}
    }
    
    //CONSUMER
    void *consumer(void *) {
    
    	int time = 10000000;
    	while(time--) {
    		pthread_mutex_lock(&mutex);
    		while (num <= 0) {
    			pthread_cond_wait(&cond, &mutex);
    			printf("The BUF is empty!!
    ");
    		}
    		num -= 1; // num > 0, so consume one product.
    		printf("Consumed one thing!,remain : %d
    ", num);
    		sleep(1); //  cost one sec to consume.
    		pthread_cond_signal(&cond); // send signal to awake the other process.
    		printf("notify the producer!!
    ");
    		pthread_mutex_unlock(&mutex);
    	}
    }
    
    int main() {
    	printf("Start int main function.
    ");
    	pthread_t thread1, thread2;
    	
    	pthread_create(&thread1, NULL , &producer, NULL);
    	
    	pthread_create(&thread2, NULL , &consumer, NULL);
    	
    	pthread_join(thread1, NULL);
    	pthread_join(thread2, NULL);
    	printf("The number is %d
    ", num);
    	return 0;
    }
    
    

    线程同步总结:

  • 相关阅读:
    DRF资源分配算法
    DC/OS快速安装部署
    安装dcos cli
    DC/OS遇到的报错
    Apache-Shiro+Zookeeper系统集群安全解决方案之会话管理
    用Jenkins+Gradle+Jetty实现持续集成、测试、部署
    构建工具之
    Spring-MVC开发之全局异常捕获全面解读
    用Hbase存储Log4j日志数据:HbaseAppender
    SSIS连接-左外连接
  • 原文地址:https://www.cnblogs.com/DengSchoo/p/12652263.html
Copyright © 2011-2022 走看看