6.11Java多线程、并发、同步、synchronized块

2021/6/12 14:26:11

本文主要是介绍6.11Java多线程、并发、同步、synchronized块,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

6.11Java多线程、并发、同步、synchronized块

synchronized块

  • 同步块:synchronized(object){},object称为同步监视器

    • object可以是任何对象,但是推荐使用共享资源作为同步监视器

    • 同步方法中无需指定同步监视器(因为监视对象是this对象本身或者class类的模子)

  • 同步监视器的执行过程

    • 第一个线程访问,锁定同步监视器,执行代码

    • 第二个线程访问,同步监视器被锁定,无法访问

    • 第一个线程访问完毕,解锁同步监视器

    • 第二个线程访问,发现同步监视器未锁,锁定并访问

synchronized块可以锁定具体的一个对象

Java当中的四种块

  • 方法当中的块--->局部块

    • 解决变量的作用域--->快速释放内存

  • 类中的块(方法外)--->构造块

    • 初始化对象信息--->对象的信息

  • 静态块(static)

    • 只加载一次

    • 初始化类

    • 先于构造块执行--->类的信息

  • 同步块--->在方法中,解决线程安全的问题--->加一个synchronized、监视对象

    • 推荐使用共享资源作为同步监视器--->只有共享的资源才可能会被多线程访问

四种块

使用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类的对象
     */
}
demo2--->容器中添加同步锁(synchronized)
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());
​
    }
}

 



这篇关于6.11Java多线程、并发、同步、synchronized块的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程