同步块:synchronized(object){},object称为同步监视器
object可以是任何对象,但是推荐使用共享资源作为同步监视器
同步方法中无需指定同步监视器(因为监视对象是this对象本身或者class类的模子)
同步监视器的执行过程
第一个线程访问,锁定同步监视器,执行代码
第二个线程访问,同步监视器被锁定,无法访问
第一个线程访问完毕,解锁同步监视器
第二个线程访问,发现同步监视器未锁,锁定并访问
synchronized块可以锁定具体的一个对象
方法当中的块--->局部块
解决变量的作用域--->快速释放内存
类中的块(方法外)--->构造块
初始化对象信息--->对象的信息
静态块(static)
只加载一次
初始化类
先于构造块执行--->类的信息
同步块--->在方法中,解决线程安全的问题--->加一个synchronized、监视对象
推荐使用共享资源作为同步监视器--->只有共享的资源才可能会被多线程访问
四种块
package iostudy.synchro; public class SynTestNo2 { /*定义资源属性*/ int money; //金额 String name; //名称字符串 public static void main(String[] args) { AccountTest accountTest = new AccountTest(100, "money"); SynDrawing you = new SynDrawing(accountTest, 80, "Lucifer"); SynDrawing she = new SynDrawing(accountTest, 90, "JunkingBoy"); you.start(); she.start(); } /*创建构造器*/ public SynTestNo2(int money, String name) { this.money = money; this.name = name; } } /** * 模拟提款机提款类--->多线程 * @since JDK 1.8 * @date 2021/6/10 * @author Lucifer */ class SafeDrawing extends Thread{ /*创建实现类对象--->面向对象的思想*/ AccountTest accountTest; //取出的账户 int drawingMoney; //取出的钱数 int pocketTotal; //取出的钱的总数 /*创建构造器,将属性定义为参数*/ public SafeDrawing(AccountTest accountTest, int drawingMoney, String name) { super(name); //线程的名称 this.accountTest = accountTest; this.drawingMoney = drawingMoney; } /*重写run方法--->线程的具体实现*/ @Override public void run() { test(); } //目标锁定不对,锁定失败 /* 这里不是锁定this,而应该锁定account */ public synchronized void test(){ /*在存钱和取钱的时候加入条件*/ if (accountTest.money-drawingMoney<0){ /*结束方法*/ return; } /*模拟取款的网络延迟*/ try { Thread.sleep(1000); }catch (InterruptedException e){ System.out.println(e.getMessage()); e.printStackTrace(); } /* 理论上说加了判断就会控制结果 但是实际上不会,这个需要对资源+锁实现控制的效果 */ /*账户的金额-取出的金额*/ accountTest.money -= drawingMoney; /*口袋中的金额+取出的钱*/ pocketTotal += drawingMoney; /*因为继承了父类所以可以直接用this--->获取线程的名称*/ System.out.println(this.getName() + "--->账户余额为:" + accountTest.money); System.out.println(this.getName() + "--->身上余额为:" + pocketTotal); } /* 该方法的this是取款机的this,应该锁住的资源是AccountTest类的对象 */ }
package iostudy.synchro; import java.util.ArrayList; import java.util.List; /** * 操作容器: * 1、这里面没有方法,要思考锁的对象 * 2、保证安全要思考锁定的范围 * @since JDK 1.8 * @date 2021/6/11 * @author Lucifer */ public class SynBlockTestNo2 { public static void main(String[] args) throws InterruptedException{ /*创建容器*/ List<String> list = new ArrayList<String>(); /*循环添加一万个线程*/ for (int i=0; i<10000; i++){ new Thread(() -> { /*加一个对象锁,保证线程的准确性*/ //同步块,保证线程安全 synchronized(list){ list.add(Thread.currentThread().getName()); } }).start(); } /*线程等待*/ Thread.sleep(10000); System.out.println(list.size()); } }