1、什么是同步,互斥。
同步一般有互斥一起讨论。在多道程序设计的操作系统中,由于存在并发执行(多个进程抢占一处理机的使用权),所以各个进程间的存在资源共享和相互合作的问题。而同步就是进程间的直接制约问题,互斥是申请临界资源进程间的间接制约问题。
2、什么是线程。
由于进程是一个拥有资源的独立单位,在各个进程抢夺处理机的被调度的过程会,系统会付出较大的时间开销,所引入了纯程,将纯程作为调度和分配资源的基本单位,用户可以通过创建线程完成任务,以减少系统开销。打开任务管理器(Ctrl+Shift+Esc),进程选项卡里正在运行的就是当前所有进程。
3、生产商与消费者(同步)
多个生产商与多个消费者共用一个仓库,这个仓库就是临界资源,生产商会不断的生产商品,消费者同样也在不断的消费,但当仓库满仓时,生产商应该停止生产了(wait()),但消费者同时还在不断的消费,当仓库有空闲仓位时,生产商就应该被唤醒(notify()),继续生产。同样消费者也是,当仓库没有商品时,消费者也应该停止消费,等生产商生产出商品后,才继续消费。
class Store {
// 仓位最多为20个
private final int MAX = 20;
private int num = 0;
/**
* 生产商生产的产品入库
*/
public synchronized void produce(Producer producer) {
while (num == MAX) {
try {
System.out.println("仓库已满 ,请等待空位");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
++num;
System.out.println(producer.name+" 生产了后,仓库现存 :" + num+"个产品");
notify();//唤醒其它进程
}
/**
* 消费者消费商品出库
*/
public synchronized void consume(Comsumer consumer) {
while (num == 0) {
try {
System.out.println("仓库空仓,请等待产品入库");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
--num;
System.out.println(consumer.name+" 消费后,还剩 :" + num+"个产品");
notify();//唤醒其它进程
}
}
/**
* 生产商类,不断地生产产品
*/
class Producer implements Runnable {
String name;
Store store;
public Producer(String name,Store store) {
this.name=name;
this.store = store;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
store.produce(this);
}
}
}
/**
* 消费者类,不断地消费产品
*/
class Comsumer implements Runnable {
String name;
Store store;
public Comsumer(String name,Store store) {
this.name = name;
this.store=store;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep((long) (Math.random() % 30 * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
store.consume(this);
}
}
}
public class Main {
public static void main(String[] args) {
Store store = new Store();
new Thread(new Comsumer("张三",store)).start();
new Thread(new Comsumer("李四",store)).start();
new Thread(new Comsumer("王五",store)).start();
new Thread(new Producer("第一工厂",store)).start();
new Thread(new Producer("第二工厂",store)).start();
new Thread(new Producer("第三工厂",store)).start();
}
}
4、车票售卖(互斥)
一个车站有多个售票窗口,如果每个售票窗口就相当于一个线程,车票就是互斥线程争夺的临界资源。为了保障信息的完整性、安全性和封闭性。所以对于临界资源必须保护起来。在java语言中就是加synchronized关键字,告诉系统,这是一个临界资源,一个只能一个线程访问。如果不加synchronized关键字,就有可能出现数据丢失或读取脏数据的错误。就以下代码,如果sale()方法没有加synchronized关键字,num就可能输出-1,-2等错误的数据,但事实上,车票是没有负数的。
class Ticket {
private int num = 10;
/**
* sale()方法代表销售车票,如果不加synchronized关键字,可能有负数输出
*/
public synchronized void sale(Window window) {
if (num > 0) {
// 输出当前有多少张车票
System.out.println(window.name + "售出票,还剩 :" + --num);
} else {
try {
// 车票售完后,所有线程等待
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 窗口类
*/
class Window implements Runnable {
String name;
Ticket ticket;
public Window(String name, Ticket ticket) {
super();
this.name = name;
this.ticket = ticket;
}
@Override
public void run() {
while (true) {
try {
// 等待[0,3)秒
long time = (long) (Math.random() * 3) * 1000;
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
ticket.sale(this);
}
}
}
public class Main {
public static void main(String[] args) {
Ticket t = new Ticket();
// 三个售票窗口,相当三个互斥线程
new Thread(new Window("窗口一", t)).start();
new Thread(new Window("窗口二", t)).start();
new Thread(new Window("窗口三", t)).start();
}
}
在eclipse中的运行结果