为什么要有同步代码块
为了保护线程的安全,举个例子在统计的时候,如果说一个线程计数到了100,在这个线程即将打印数据的时候cpu的使用权被抢走,另一个线程将计数加1,等待原本的线程抢夺回cpu使用权时,打印的数据已经是错误的了。
同步代码块需要一个锁对象
锁对象一定是唯一的,它可以是任何类型的数据如
static Object obj=new Object();
MyThread.class//使用文件编译成的字节码文件对象也是可以的
public class MyThread extends Thread{
static int ticket=0;
@Override
public void run() {
while(true){
synchronized (MyThread.class){//锁对象一定要是唯一的->static
if(ticket<100){
try {
Thread.sleep(10);//父类中的run方法是使用try环绕的,所以子类的只能try
} catch (InterruptedException e) {
e.printStackTrace();
}
ticket++;
System.out.println(getName()+"卖了第"+ticket+"张票w");
}else {
break;
}
}
}
}
}
细节
1、同步代码块不可以写在循环的外边
这是因为线程的是释放条件是执行完同步代码块内部的代码,如果写在循环的外边,线程会一直占据循环的代码,其他线程会卡在锁的外面。
在自己定义的锁和开锁方法时,如果说在循环中使用break关键字跳出的时候,但是没有调用开锁方法,其他线程会卡死在锁门口导致整个程序无法停止。
2、锁对象必须是唯一的
我们一般将锁对象设置为当前字节码文件的对象。
如果进入一间屋子每个人都有自己的门,就相当于没有门。