何为互斥?互斥就是比如一个东西在被一个用户使用时就不能被另一个用户所使用。
何为同步?同步就是一个进程的结束时另一个进程的开始,就好比时A程序的输出完成,B经常才能开始输入。
进程同步方法
我们常用的方法就是实现信号量机制。常用的信号量机制有三种,分别是整型信号量,结构体型信号量和AND型信号量
整型信号量
整型信号量是用一个整数来表示资源的数目,当资源被使用是执行S--,当资源被释放的时候S++,分别对应两个函数wait和signal
wait函数是当S>0时(此时表示有资源可用否则表示无资源可用)执行wait方法,最后再S--,如果S一直小于0,那wait方法就会一直等待下去,<--------这也是这种信号量的缺点。
signal函数时当S<0时(此时表明无资源)执行signal函数,最后S++。
可以简单的理解为S为食物,当没食物的时候,wait函数一直等着食物来,而食物则需要signal函数来做,当signal函数做出来一份食物后,wait函数才能开始吃
wait(S){
while(S<=0);
S--;
}
signal(S){
S++;
}
缺点:上面提到的当S一直小于0的时候,wait函数会一直处于死循环,属于“忙等”状态。
AND型信号量
AND型信号量比较直接,它会将所有的资源全部分配给进程,当此进程全部执行完之后才执行下一个进程,要么将所有资源全部分配给一个进程,要么一点资源也不分配,这样就可以避免出现死锁的问题。
wait(S1,S2,...,Sn)
{
while(true)
{
if(Si>=1&&...&&Sn>=1)
{
for(i=1;i<n;i++)
Si--;
break;
}
else
{
place the process in the waiting queue associated with.....
//如果没有申请到资源的话就挂到相应的阻塞队列里去
}
}
}
Ssignal(S1,S2,...Sn)
{
while(true)
{
for(i=1;i<=n;i++)
{
Si++;
remove all the process waiting in the queue associated with Si into the ready queue;
//去后备队列里唤醒或移除因Si资源阻塞的进程
}
}
}
互斥关系
假设两个进程A和进程B,他们共用一个资源,此时进程A在使用改资源,进程B就不能使用,怎么让进程A使用共用资源的时候进程B无法使用呢?这时候就需要设置一个信号量mutex,首先假设初始资源为1,也就是mutex=1,此时进程A使用资源,调用wait函数,使mutex-1,此时mutex=0,进程B就无法进入wait函数调用公用资源,而当进程A执行完之后会执行signal函数,使mutex+1,然后进程B就可以执行wait函数调用公共资源了。
semaphore mutex=1;
PA(){
while(1){
wait(mutex);
临界区
signal(mutex);
剩余区
}
}
PB(){
while(1){
wait(mutex);
临界区
signal(mutex);
剩余区
}
}
用java实现进程同步
package cc.os.pc;
/**
* 进程同步---生产者-消费者问题
* @author 季夏
*/
public class PC {
public static void main(String[] args) {
/**
* 防伪信息
* */
System.out.println("------------------------------");
System.out.println();
System.out.println(" 操作系统原理-0004班第3组");
System.out.println();
System.out.println("------------------------------");
Bread bread = new Bread();
Thread rouBaoZi = new Thread(new Producter(bread, "大厨师"));
Thread suBaoZi = new Thread(new Producter(bread, "小厨师"));
Thread customerZS = new Thread(new Customer(bread, "顾客A"));
Thread customerLS = new Thread(new Customer(bread, "顾客B"));
customerZS.start();
rouBaoZi.start();
suBaoZi.start();
customerLS.start();
}
}
/**
* 消费者进程
*/
class Customer extends Thread {
private String name;
private Bread bread;
public Customer() {
}
public Customer(Bread baoZi, String name) {
this.bread = baoZi;
this.name = name;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(2000); //休眠两秒钟
bread.buy(name); //消耗一个面包
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 生产者进程
*/
class Producter extends Thread {
private String name; //厨师名字
private Bread bread; //缓冲区面包资源
public Producter() {
}
public Producter(Bread bread, String name) {
this.bread = bread;
this.name = name;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(2000); //休眠两秒钟
bread.make(name); //生产一个面包资源
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 定义缓冲器余量,生产者和消费者执行的方法
*/
class Bread {
/**
* 这里count代表面包数,也是公共区资源数,设置上限为2
* */
Integer count = 0;
/**
* 生产面包
* @param name 厨师名
*/
public synchronized void make(String name) {
// 判断面包数是否大于2达到上限
while (count >= 2) {
try {
wait(); //面包容量达2,超出上限,生产者进入等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++; //如果没有达到2就做一个面包
System.out.println(name + ":做了一个,还剩【" + count + "】个!");
notifyAll(); //有面包资源了,唤醒消费者购买面包
}
/**
* 购买面包(使用资源)
* @param name 消费者名
*/
public synchronized void buy(String name) {
// 判断面包资源数是否等于0,
while (count == 0) {
try {
wait(); //没有面包资源,消费者进程进入等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--; //面包资源数量减一
System.out.println(name + ":购买了一个面包,面包资源剩余【" + count + "】个!");
notifyAll(); //面包数未达到上限,让生产者厨师做面包,(唤醒所有等待该资源的进程),
}
}