死锁
两个或多个线程之间使用了互斥锁,然后一方锁上了之后就睡眠等待其他线程,这时同步代码块还没执行完,就到其他线程了,其他线程也锁上了再睡眠,等待一开始的线程,但是一开始的线程在等待最后的线程执行完释放资源,但是一开始的线程不执行完,那么最后的线程也不会执行完,就僵持了,这样就出现了死锁。
线程同步
两种方式:同步方法和同步代码块
同步方法
在方法上加synchronized变为同步方法,是给当前类对象加锁
非静态方法,锁在this
静态方法。,所在类.class
锁的释放
在同步方法执行完才释放锁
同步方法的锁的范围太大了,整个方法都被锁住了,其中如果有不需要同步执行的代码的话就太浪费资源了,效率很低,所以可以使用同步代码块。
public synchronized void pick(){ if (num>0){ System.out.println(Thread.currentThread().getName()+"取走了50W"); num-=50; } }
同步代码块
synchronized(锁对象) { //括号里可以是对象,类。class
}
private int state; private static Wan w = new Wan(); private static Kuaizi k = new Kuaizi(); public void Eat(){ if (state==0){ synchronized (k){ System.out.println(Thread.currentThread().getName()+"找到了筷子"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (w){ System.out.println(Thread.currentThread().getName()+"找到了碗"); } } if (state==1){ synchronized (w){ System.out.println(Thread.currentThread().getName()+"找到了碗"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (k){ System.out.println(Thread.currentThread().getName()+"找到了筷子"); } } }
同步的缺点
效率低
会造成死锁
public class Test {
public static void main(String[] args) {
Test test = new Test();
new Thread(new Runnable() {
@Override
public void run() {
test.one();
}
},"A").start();
new Thread(new Runnable() {
@Override
public void run() {
test.two();
}
},"B").start();
new Thread(new Runnable() {
@Override
public void run() {
test.three();
}
},"C").start();
new Thread(new Runnable() {
@Override
public void run() {
four();
}
},"D").start();
}
//非静态同步方法
public synchronized void one(){
System.out.println("one..");
try {
Thread.sleep(1000);//只会释放cpu资源,但是不会释放锁,同步如果没有释放锁,那么抢占到资源也不糊运行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//非静态同步方法
public synchronized void two(){
System.out.println("two..");
}
//普通方法
public void three(){
System.out.println("three....");
}
//静态同步方法
public synchronized static void four(){
System.out.println("four....");
}
}
笔记
Runnable实现的线程,必须是同一个runnable的对象new出来的线程才共享资源。
Test03 test03 = new Test03(); new Thread(test03,"张三").start(); new Thread(test03,"张三老婆").start();