Java基础学习:多线程20(线程同步:Synchronized)
-
线程同步:Synchronized(同步方法、同步代码块)
-
同步方法:
-
由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是synchronized关键字,它包括2种方法:
//synchronized 方法和 synchronized块:
//同步方法:
public synchronized void method(int ...){...};
-
synchronzed方法控制“对象”的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行;
//缺陷:若将一个大的方法声明为synchronized将会影响效率
-
synchronzed的实现原理:队列+锁;
-
-
同步方法的弊端:
-
方法里面需要修改的内容才需要锁;
-
锁的太多,浪费资源;
-
-
同步块:
-
同步块语法:
synchronized (Obj) { }
//Obj称之为同步监视器;
//Obj可以是任意对象,但是推荐使用共享资源作为监视器; -
同步方法种无需指定同步监视器,因为同步方法的同步监视器就是this,就是这个对象本身,后者是class[反射种讲解];
-
-
同步监视器的执行过程:
-
-
第二个线程访问,发现同步监视器被锁定,无法访问;
-
第一个线程访问完毕,解锁同步监视器;
-
第二个线程访问,发现同步监视器没有锁,然后锁定并访问;
-
-
-
修改之前的三个不安全案例
package com.ljx3.syn;
/**
* 不安全的买票:
* 1,线程不安全,有负数;
* 2,
*
*/
public class UnSafeBuyTicket {
public static void main(String[] args) {
//声明一个买票对象
BuyTicket b=new BuyTicket();
//三个人买票
new Thread(b,"小明").start();
new Thread(b,"老师").start();
new Thread(b,"黄牛党").start();
}
}
//买票
class BuyTicket implements Runnable{
//票
private int ticketNums=10;
boolean flag=true;//外部停止方式
-
代码案例:list加锁
package com.ljx3.syn;
import java.util.ArrayList;
import java.util.List;
/**
* 线程不安全的集合:
*
*/
public class UnSafeList {
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());//9997
}
}
-
笔记:
-
synchronized:默认锁定是this,是它本身;
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律