同步代码
1.语法结构
synchronized (同步监听对象) {
可能引发线程安全问题的代码
}
上面的结构相当于把{ }中的代码捆绑成一个整体,线程只能够一个一个的进来,执行完一个,下一个才能进来。
2.语法特点
- 上面的同步监听对象可以是任意的对象(必须确保大家用的是同一把锁);
- 保证所有的线程共享一个同步监听对象的;也就是保证被同步监听对象是被所有线程共享的。
- 很多时候可以写this,但是请先参照②,
- 常用的方式:使用类的字节码对象 XXX.class
public class TicketThread extends Thread{
private static int num = 50;
public void run() {
while(num>0){
// 只应该同步销售的一张票的操作代码
synchronized (TicketThread.class) {
// 下面的代码是销售一张票,每卖一张票的前提判断是否有票
if(num>0){
System.out.println(this.getName()+"您的票号是:"+num);
num--;
}
}
}
}
同步方法
1、就是在需要被同步的方法上面加关键字 synchronized
2、加的位置 :在返回值类型的前面
3、不需要也不能够显示的写同步监听对象
4、如果是一个非static的方法,那么同步监听对象就是this;
5、如果是static修饰的方法,那么同步监听对象就是当前方法所在的类的字节码对象
public class TicketThread implements Runnable{
private int num = 50;
public void run() {
while(num>0){
saleOne();
}
}
private synchronized void saleOne(){
if(num>0){
System.out.println(" 您的票号是:"+num);
num--;
}
}
}
锁机制
1、创建ReentrantLock对象
2、调用lock方法:加锁
{代码....}
3、调用unlock方法:解锁
注意:可把解锁的unlock方法的调用放在finally{}代码块中,保证一定能解锁
public class Ticket extends Thread {
public Ticket(String name) {
super(name);
}
static Lock lock = new ReentrantLock();//必须保证多个线程访问的是同一把锁
static int num = 50;
@Override
public void run() {
while(num > 0){//循环判断,是否有就卖
lock.lock();
try {
if(num>0){//判断卖一张票的操作
System.out.println(getName()+" 您的票号是:"+num);
num--;
}
} finally {
lock.unlock();
}
}
}
}
ps:
继承Thread类的方式:每当存在几个线程就需要创建几个对象,因此要特别注意所有线程访问的是同一对象,确保是同一把锁
实现Runnable接口的方式:不管存在几个线程都只需要创建一个对象,因此一定访问的是同一个对象