线程安全:
多个线程访问同一资源,有可能产生线程安全问题。
解决线程安全:
synchronized关键字:
synchronized代码块:
synchronized(对象){可以是任意类型的的对象,但是要保证多个线程访问同一锁对象
有可能发生线程安全问题的代码
同时只能有一个线程进入该代码块
只有把synchronized代码块中的代码全部执行完毕以后,会自动释放锁对象
}
synchronized方法:
static:锁对象是当前类的反射对象。一个类只能用一个反射对象。
非static:锁对象是this
package day18;
public class Test6 {
static int b=100;
public static void main(String[] args) {
Runnable r=new Runnable() {
@Override
public void run() {
int a=0,d=0;
String name=Thread.currentThread().getName();
while(true) {
synchronized (this){
if(b==0)
break;
System.out.println(name+"正在卖第"+b+"包");
b--;
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if("官网".equals(name))
a++;
if("实体店".equals(name))
d++;
}
if("官网".equals(name))
System.out.println(a);
if("实体店".equals(name))
System.out.println(d);
}
};
Thread t=new Thread(r,"官网");
Thread t1=new Thread(r,"实体店");
t.start();
t1.start();
}
}
synchronized:
底层的锁:无锁(无锁可偏向,无所不可偏向)、轻量级锁、重量级锁
没有开启偏向锁的情况下:
一个对象没有被作为锁对象,处于无锁状态
一个对象被一个线程获取作为锁对象,处于轻量级锁状态
一个线程已经持有了该锁对象,其他线程来争用,处于重量级锁状态。
开启偏向锁的情况下:
一个对象没有被作为锁对象,处于无锁可偏向状态。(对象头中没有记录线程ID)
一个对象被一个线程作为锁对象,处于轻量级锁状态。(对象头中记录了线程ID)
一个对象被一个线程作为锁对象,释放锁对象后(但是该线程没有消亡时),其他线
程再获取该锁对象,则处于轻量级锁状态。
一个对象被一个线程作为锁对象,没有释放锁,其他线程也要获取该锁对象,就处
于重量级锁状态。
偏向锁 :
大部分情况下,锁不仅不存在竞争,而且总是由一个线程多次获得,为了让获取锁的
代价更低,就有了偏向锁。
当一个线程使用synchronized方式获取一个锁对象时,会在该对象的对象头中存储当前
线程的id,后续这个线程再去获取该锁对象时,直接进行线程id的比较成功就表示该锁
是偏向当前线程的,不需要再次获取锁了 。