同步代码块(悲观锁)
同步对象:必须保证几个线程对象共享的是同一个同步对象
- static修饰的对象只有一份,在静态区
- 字节码文件 Xxx.class文件只有一份,在元空间【建议使用当前类的字节码文件】
public class TicketThread extends Thread {
private static int ticket = 50;//实例变量
private static Object obj = new Object();//线程同步对象
public TicketThread(String s) {
super(s);
}
@Override
public void run() {
while (ticket > 0) {
saleOne();
}
}
private void saleOne() {
synchronized (obj) {//加锁,obj必须被几个线程对象共享
//obj可以是static,也可以是元空间的字节码文件,
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "当前票号是:" + ticket);
ticket--;
}
}
}
}
同步方法(悲观锁)
用synchronized关键字修饰方法
- 如果方法是static修饰的:同步的是 :当前类.class
- 如果方法是非static修饰的:同步的是: this
如果继承Thread的方式,同步方法的话,就需要将方法改为static修饰,所以说,一般我们不用同步方法,一般建议继承Thread用同步代码块或者锁机制
public class TicketThread extends Thread {
private static int ticket = 50;//实例变量
public TicketThread(String s) {
super(s);
}
@Override
public void run() {
while (ticket > 0) {
saleOne();
}
}
private static synchronized void saleOne() {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "当前票号是:" + ticket);
ticket--;
}
}
}
锁机制: Lock接口的实现类ReentrantLock【可重入互斥锁】(乐观锁)
锁原则:最小范围原则,为了保证执行效率
public class TicketThread extends Thread {
private static int ticket = 50;//实例变量
private final ReentrantLock lock = new ReentrantLock();// 不要公平机制。效率高
public TicketThread(String s) {
super(s);
}
@Override
public void run() {
while (ticket > 0) {
saleOne();
}
}
private void saleOne() {
lock.lock();//上锁
try {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "当前票号是:" + ticket);
ticket--;
}
}finally {
lock.unlock();//释放锁
}
}
}