关于同步与互斥
线程是进程的最小单元,同一进程中有多个线程
线程的交互有:互斥与同步
同步:因为线程之间的合作,如有线程A将计算结果提供给线程B作进一步处理,那么线程B在线程A将数据送达之前都将处于阻塞状态。
互斥:系统中的多个线程必然要共享某种系统资源,如共享CPU,共享I/O设备,所谓间接相互制约即源于这种资源共享,打印机就是最好的例子,线程A在使用打印机时,其它线程都要等待,这就是互斥
线程A和线程B互斥访问某个资源则它们之间就会产个顺序问题——要么线程A等待线程B操作完毕,要么线程B等待线程操作完毕,这其实就是线程的同步了
同步包括互斥,互斥是一种特殊的同步
线程的方法
互斥的实现:synckronized(lockObj–创建的锁对象)
lockObj.wait()方法是让线程等待,后面需要用lockObj.notify()或者lockObj.notyfyAll()方法使线程唤醒,这两个通常是成对出现的
如何理解同步 Wait Set(即线程等待区)
当一个线程获得资源的时候,会有锁,当线程获得的资源不够的时候,会调用wait()方法,释放获得的对象锁,并进入Wait Set区,让出资源来让后续的线程获取资源来做事,同第一个线程一样,后续的线程也有可能会wait(),也跟着进入了Wait Set区,当后续的线程执行的差不多了,结束了,要调用notify()去唤醒之前在Wait Set里的线程,或者notifyAll()唤醒所有线程重新抢占资源
演示代码如下:
线程同步经典问题重现:生产者与消费者模型
当生产者生产一个资源后,消费者消费一个资源,如果没有资源,消费者等待生产者生产资源
//生产者和消费者模型
//设置公共资源
class PublicResource{
private int number=0;
//增加公共资源
//synchronize是关键字,同static用法,用在方法的前面,表示同步
public synchronized void increase(){
while(number!=0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;
System.out.println("生产1个资源,总资源为:"+number);
notify();
}
//减少公共资源
public synchronized void decrease(){
while(number==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number--;
System.out.println("消耗1个资源,总资源为:"+number);
notify();
}
}
//创建生产者线程,负责生产资源
class ProducerThread implements Runnable{
private PublicResource resource;
public ProducerThread(PublicResource resource) {
this.resource = resource;
}
@Override
public void run() {
for(int i=0;i<10;i++){
try {
//睡眠0~1秒的时间
Thread.sleep((long)(Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
resource.increase();
}
}
//创建消费者线程,负责生产资源
class UserThread implements Runnable{
private PublicResource resource;
public UserThread(PublicResource resource) {
this.resource = resource;
}
@Override
public void run() {
for(int i=0;i<10;i++){
try {
//睡眠0~1秒的时间
Thread.sleep((long)(Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
resource.decrease();;
}
}
//创建消费者
public class ProduceAndUse {
public static void main(String[] args) {
PublicResource resource = new PublicResource();
new Thread(new UserThread(resource)).start();
new Thread(new UserThread(resource)).start();
new Thread(new UserThread(resource)).start();
new Thread(new ProducerThread(resource)).start();
new Thread(new ProducerThread(resource)).start();
new Thread(new ProducerThread(resource)).start();
}
}
结果为: