实现多线程同步Lock锁与 synchronized 同步监视器的区别`
线程同步的关键:
确保一个时间点只有一个线程访问共享资源。可以给共享资源加一把锁,哪个线程获取了这把锁,才有权利访问该共享资源。
1.同步监视器
同步监视器可以是任何对象,必须唯一,保证多个线程获得是同一个对象(锁).
同步监视器的执行过程
1.第一个线程访问,锁定同步监视器,执行其中代码.
2.第二个线程访问,发现同步监视器被锁定,无法访问.
3.第一个线程访问完毕,解锁同步监视器.
4.第二个线程访问,发现同步监视器没有锁,然后锁定并访问.
缺点:一个线程持有锁会导致其他所有需要此锁的线程挂起;在多线程竞争下,加锁,释放锁会导致比较多的上下
文切换和调度延时,引起性能问题.
synchronized 同步监视器的使用
synchronized 可作用于一个方法,为此方法加同步监视器
也可以错用于某段代码synchronized(同步监视器){要同步的代码}
例题:模拟卖票:
package com.ff.Javathread.day2.Demo2;
public class Sellticke implements Runnable {
int ticket = 10;//当实现Runnable接口时不用设置为static
Object o[]=new Object[10];
@Override
public void run() {
/*while (true) {
synchronized (o) {//synchronized对代码块进行监视
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ":" + ticket);
ticket--;
}
}
}*/
while (true) {
if (ticket > 0) {
Sell();
} else {
break;
}
}
}
//用synchronized修饰方法,此方法为同步方法
//synchronized修饰方式时,锁对象默认为this,多个线程就有多把锁
public synchronized void Sell(){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ":" + ticket);
ticket--;
}
}
}
public class Tste {
public static void main(String[] args) {
Sellticke s=new Sellticke();
Thread t=new Thread(s,"窗口1");
Thread thread=new Thread(s,"窗口2");
t.start();
thread.start();
}
}
2.死锁
死锁就是两个线程占用了彼此的同步资源,两个线程都不愿意放弃自己的同步资源而导致两个线程都无法执行完成,而导致的死锁
出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续.
就像是在一条比较窄马路上两辆车相遇,两辆车并行谁都没办法通过,但是谁都不愿意往后退一点,最后导致阻塞,谁也没办法走.
给出一个死锁的例子:
package com.ff.Javathread.d