synchonized关键字
- (1)关键字表示的含义是[同步]
- (2)有什么用?
可以修饰代码块,也可以修饰方法,前者同步代码块
,后者同步方法
它可以是任意的对象 锁对象``只是做一个标记
,只有持有锁对象的线程才能够进行到同步代码块。
- (3)同步代码块的作用
保证只有持有锁对象的线程才能进入到同步代码块中, 这样就可以避免多个线程共同操作的共享数据 - (4)修复卖票程序
class SaleTicket implements Runnable {
int tikets = 100;//1: 100张票
//锁对象:只是一个标记相当于true,false,任何对象都可以
private static final Object lock = new Object();
@Override
public void run() {
//逻辑代码
while (true) {
try {
Thread.sleep(50);//磨叽
} catch (InterruptedException e) {
e.printStackTrace();
}
//判断是否有锁,如果有锁则获得锁,进入代码块,否则,只有在代码块外等锁
synchronized (lock){//获得锁
//如果票数> 0 ,退出
if (tikets > 0) {
tikets--;
System.out.println("还剩余" + tikets + "张");
}else{
break;
}
}//释放锁
}
}
}
同步方法的使用
- (1)如果synchroznied修饰方法,那么就是同步方法
- (2)同步方法的作用
同步方法相当于把整个的方法体加了同步代码块。 - (3)如果这个方法是
非静态
的,那么这个锁对象是this
- (4)如果这个方法是
静态
的,那么这个锁对象是当前类类名.class
class SaleTicket implements Runnable {
static int tikets = 100;//1: 100张票
//锁对象:只是一个标记相当于true,false,任何对象都可以
@Override
public void run() {
//逻辑代码
while (true) {
try {
Thread.sleep(50);//磨叽
} catch (InterruptedException e) {
e.printStackTrace();
}
sell2();
}
}
//判断是否有锁,如果有锁则获得锁,进入代码块,否则,只有在代码块外等锁
synchronized void sell (/* this */){//获得锁
//如果票数> 0 ,退出
if (tikets > 0) {
tikets--;
System.out.println("还剩余" + tikets + "张");
}
}//释放锁
//判断是否有锁,如果有锁则获得锁,进入代码块,否则,只有在代码块外等锁
synchronized static void sell2 (/* SaleTicket.class */){//获得锁
//如果票数> 0 ,退出
if (tikets > 0) {
tikets--;
System.out.println("还剩余" + tikets + "张");
}
}//释放锁
}
- 一句话小结:如果方法内 多个线程去改同一份数据,必须加synchronized关键字
线程的6种状态***
- (1)新建 new Thread() new Thread子类()
- (2)运行(调用start方法)
- (3)受阻塞
当一个线程没有拿到锁,只能等待其他线程释放锁
当一个线程等到了锁,就可以回到运行状态 - (4)计时等待
当一个线程调用了sleep(millis)或者wait(millis) 睡醒之后,不需要锁,改成运行。 需要锁,改成 受阻塞。 - (5)无限等待
当一个线程调用了wait方法(这个是Object的方法)那么这个线程就会进入无限等待,除非调用notify
改成 运行。 不需要锁
改成 受阻塞。 需要锁 - (6)退出
当线程的run方法结束或者调用了 stop方法
死锁
- (1)两个以上的线程,每个线程各自持有一把锁,并且等待其他线程释放锁。
- (2)死锁不是好的代码,是有问题的代码
public class Demo08 {
private static Object lockA = new Object();
private static Object lockB = new Object();
//只有同时有两把锁才能执行代码
private static class Task1 implements Runnable {
@Override
public void run() {
while (true) {
synchronized (lockA) {//获取了锁A 进入房间1
System.out.println("获取了锁A 进入房间1");
synchronized (lockB) {//获取了锁B 进入房间2
System.out.println("获取了锁B 进入房间2");
System.out.println("执行了 Task1");
}//释放锁B 出房间2
}//释放锁A 出房间1
}
}
}
private static class Task2 implements Runnable {
@Override
public void run() {
while (true) {
synchronized (lockB) {
System.out.println("获取了锁B 进入房间2");
synchronized (lockA) {
System.out.println("获取了锁A 进入房间1");
System.out.println("执行了 Task2");
}
}
}
}
}
public static void main(String[] args) {
Task1 task1 = new Task1();
Task2 task2 = new Task2();
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
t1.start();
t2.start();
}
}