进程同步与互斥实验代码_python笔记46:进程同步机制:互斥锁与信号量

主要内容:

  • 小目标:掌握进程同步机制
  • 主要内容:Lock

如果看完这篇文章,你还是搞不懂并发同步及锁机制,

你来找我,我保证不打你,我给你发100的大红包。

1. 同步机制

  • 并发编程中存在异步问题,如何处理?

使用同步机制,

常见的同步机制包括锁,信号量;

同步机制: 一个例子:公共资源,互斥锁,AB两个进程

修改公共资源流程

进程修改公共资源,需要获取锁;

修改资源;

释放锁;

两个进程:

A进程获取锁,同时去修改公共资源;

进程调度切换,执行B进程;

B进程去获取锁,但是A进程已经占有锁,B进程被挂起;

A进程修改完毕,释放锁;

B进程被唤起,修改资源并释放锁;

2. Value与Array自带锁机制

Value与Array创建对象参数:

Value(typecode_or_type, *args, lock=True)Array(typecode_or_type, size_or_initializer, *, lock=True)

lock默认值为True:代表支持锁机制;

相关方法:

b8c2770b7d58db1c0394856eb459dcfe.png

Value自带锁机制

使用方式:

lock = val.get_lock()#打印lock信息print(lock)val.acquire()#打印lock信息print(lock)val.value = 100val.release()

结果:每次lock之后,锁会显示状态;

3. 锁机制应用

两个进程使用同步机制对Value对象修改:

主进程加100000次;子进程减100000次;

代码如下:

import multiprocessingfrom multiprocessing import Queuefrom multiprocessing import Value, Arrayg_value = Value('i', 0)#对g_value处理封装成函数def deal(gvalue, val):    gvalue.acquire()    gvalue.value += val    gvalue.release()#进程函数, 共享内存必须通过参数传入def func(gvalue):    i = 0    while i < 100000:        #加1        deal(gvalue, 1)        i += 1if __name__ == "__main__":    print("g_value init value:", g_value.value)    #全局消息队列    main_msgq = Queue()    #消息队列必须通过参数传入到子进程,否则无效    p = multiprocessing.Process(target=func, args=(g_value,))    p.start()    i = 0    while i < 100000:        #减1        deal(g_value, -1)        i += 1    p.join()    print("g_value  end value:", g_value.value)

结果:符合预期,最后g_value的值为0;

g_value init value: 0g_value  end value: 0

4. 重入锁:Lock

  • Lock相关方法:

方法说明:

de29ea314d659d045f1398d0c9b77561.png

重入锁

一个例子:

lock = Lock()lock.acquire()#此处处理公共资源lock.release()

注意:

acquire与release必须成对出现;

lock.acquire中可以设置非阻塞模式:block=False,如果获取失败返回False

  • 死锁问题

一个进程获取锁之后,再次获取,就会造成死锁; 例:

lock = Lock()lock.acquire()lock.acquire()#处理公共资源lock.release()lock.release()

一般没人这么做,但是有人这么做:

lock = Lock()lock.acquire()def do():    lock.acquire()    #处理公共资源    lock.release()lock.release()

解决方式:重入锁;

5. 冲入锁:RLock

RLock:可以被一个程多次获取; 使用方式与Lock类似; 例如:

rlock = RLock()rlock.acquire()rlock.acquire()print(rlock)rlock.release()rlock.release()print('over')

不会死锁

6. 信号量:Semaphore

Semaphore:可以设置同时被占有的次数;

相关方法:

56468e56a06fe523fcb90a69deb9cd8d.png

信号量

Semaphore使用方式与Lock类似,但是它可以指定被占有次数; 例如:

sem = Semaphore(2)print('init:', sem.get_value())sem.acquire()print('acquire 1:', sem.get_value())sem.acquire()print('acquire 2:', sem.get_value())sem.release()print('release 1:', sem.get_value())sem.release()print('release 2:', sem.get_value())

结果:

init: 2acquire 1: 1acquire 2: 0release 1: 1release 2: 2

总结:

  • Lock,RLock,Semaphore原理与使用方式类似,在掌握Lock后,在理解其他就比较容易;
  • 互斥所,信号量这种同步机制在其他一些语言中也同样适用;
  • Lock,RLock适用于同一时刻只能一个进程占有场景;
  • Semaphore比较灵活,可以设置同时占有的数量;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的进程同步互斥实验代码,供参考: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; // 共享缓存区 int in = 0, out = 0; // 生产者和消费者的指针 pthread_mutex_t mutex; // 互斥 sem_t empty, full; // 空缓存区和满缓存区信号 void *producer(void *arg) { int item = 1; while (1) { sleep(1); // 生产者生产一个产品需要1秒钟 sem_wait(&empty); // 等待空缓存区信号 pthread_mutex_lock(&mutex); // 加 buffer[in] = item; printf("Producer produce item %d, in = %d\n", item, in); in = (in + 1) % BUFFER_SIZE; item++; pthread_mutex_unlock(&mutex); // 解 sem_post(&full); // 发送满缓存区信号 } } void *consumer(void *arg) { int item; while (1) { sem_wait(&full); // 等待满缓存区信号 pthread_mutex_lock(&mutex); // 加 item = buffer[out]; printf("Consumer consume item %d, out = %d\n", item, out); out = (out + 1) % BUFFER_SIZE; pthread_mutex_unlock(&mutex); // 解 sem_post(&empty); // 发送空缓存区信号 } } int main() { pthread_t p, c; pthread_mutex_init(&mutex, NULL); sem_init(&empty, 0, BUFFER_SIZE); // 初始化空缓存区信号 sem_init(&full, 0, 0); // 初始化满缓存区信号 pthread_create(&p, NULL, producer, NULL); pthread_create(&c, NULL, consumer, NULL); pthread_join(p, NULL); pthread_join(c, NULL); pthread_mutex_destroy(&mutex); sem_destroy(&empty); sem_destroy(&full); return 0; } ``` 在这个代码中,我们使用了互斥(`pthread_mutex_t`)和信号(`sem_t`)来实现进程同步互斥。生产者和消费者进程通过互斥来访问共享缓存区,通过信号来实现进程同步。 在主函数中,我们首先初始化互斥信号,然后创建生产者和消费者进程,并等待它们结束。最后,我们释放互斥信号。 希望这个简单的代码能够帮助你更好地理解进程同步互斥的实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值