首页 > 其他分享 >线程 synchroized

线程 synchroized

时间:2022-09-30 06:22:05浏览次数:47  
标签:account 同步 Thread synchronized 线程 synchroized public

线程 synchroized

synchroized 同步方法

由于我们可以通过 private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提岀一套机制,这套机制就是 synchronized 关键字。它包括两种用法 synchronized方法和 synchronized 块。

同步方法

public synchronized void method (int args) {

}

synchronized 方法控制对 “对象" 的访问。

每个对象对应一把锁,线程中使用 对象 调用 synchronized 方法 都必须获得 该对象的锁才能执行 synchronized 方法,否则线程会阻塞。方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行。

缺陷:若将一个大的方法申明为 synchronized 将会影响效率。

package com.gcbeen.thread;

// 安全买票
public class TestSafeBuyTicket {
    public static void main(String[] args) {
        SafeBuyTicket buyTicket = new SafeBuyTicket();
        new Thread(buyTicket, "张三").start();
        new Thread(buyTicket, "李四").start();
        new Thread(buyTicket, "王五").start();
    }
}


class SafeBuyTicket implements Runnable {
    // 票
    private int ticketNums = 10;
    boolean flag = true;

    @Override
    public void run() {
        // 买票
        while (flag) {
            try {
                buy();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // synchronized 同步方法
    // 买票
    private synchronized void buy() {
        // 判断是否有票
        if (ticketNums <= 0) {
            flag = false;
            return;
        }
        // 延迟
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 买票
        System.out.println(Thread.currentThread().getName()
                + "拿到" + ticketNums--);
    }
}


// 张三拿到10
// 张三拿到9
// 张三拿到8
// 张三拿到7
// 张三拿到6
// 张三拿到5
// 张三拿到4
// 张三拿到3
// 张三拿到2
// 王五拿到1

synchroized 同步块

同步块

synchronized (Obj) {

}

obj称之为同步监视器

Obj可以是任何对象,但是推存使用共享资源作为同步监视器。

同步方法中无需指定同步监视器,因为同步方法的同步监视器就是this,就是这个对象本身,或者是class。

同步监视器的执行过程

  1. 第一个线程访问,锁定同步监视器,执行其中代码;

  2. 第二个线程访问,发现同步监视器被锁定,无法访问;

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

  4. 第二个线程访问,发现同步监视器没有锁,然后锁定并访问。

锁的对象就是变量,需要增删改查的对象

安全的取钱

package com.gcbeen.thread;

// 安全的取钱 同步块
public class TestSafeBank {

    public static void main(String[] args) {
        SafeAccount account = new SafeAccount(100, "养老基金");
        SafeDrawing drawing = new SafeDrawing(account, 60, "夸克");
        SafeDrawing same = new SafeDrawing(account, 60, "same");
        drawing.start();
        same.start();
    }

}


class SafeAccount {
    int money;  // 余额
    String cardName;    // 卡名

    public SafeAccount(int money, String cardName) {
        this.money = money;
        this.cardName = cardName;
    }
}

class SafeDrawing extends Thread {
    SafeAccount account;    // 账户
    int drawingMoney;   // 取余额
    int nowMoney;   // 个人手里的钱

    public SafeDrawing(SafeAccount account, int drawingMoney, String name) {
        // super(name) =  父类构造方法(name)
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }

    // 取钱
    @Override
    public void run() {
        // 锁的对象就是变量的量,需要增删改查的对象
        synchronized (account) {
            // 判断是否有钱
            if (account.money - drawingMoney < 0) {
                System.out.println(Thread.currentThread().getName() + "余额不足,不能进行取钱");
                return;
            }
            try {
                Thread.sleep(1000); // 放大问题的发生性
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 卡内金额 = 余额 - 个人手里的钱
            account.money = account.money - drawingMoney;
            // 个人手里的钱
            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.cardName + "余额为:" + account.money);
            // this.getName()==Thread.currentThread().getName()
            System.out.println(this.getName() + "手里的钱:" + nowMoney);
        }
    }
}

// 养老基金余额为:40
// 夸克手里的钱:60
// same余额不足,不能进行取钱

方法里面需要操作共享资源的代码才需要加锁。锁太多浪费资源

线程安全的集合

package com.gcbeen.thread;

import java.util.ArrayList;
import java.util.List;

// 线程安全的集合 同步块
public class TestSafeList {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for (int k = 0; k < 3; k++) {
            new Thread(() -> {
                for (int i = 0; i < 10000; i++) {
                    synchronized (list) {
                        list.add(Thread.currentThread().getName());
                    }
                }
            }).start();
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }

}
// 30000

标签:account,同步,Thread,synchronized,线程,synchroized,public
From: https://www.cnblogs.com/gcbeen/p/16743654.html

相关文章

  • 线程的实现-线程的创建(三种方式)
    线程实现线程的创建(三种方式)1.继承Thread类(重要)自定义线程类继承Thread类;重写run()方法,编写线程执行体;创建线程对象,调用start()方法启动线程。packagecom.gcbee......
  • 委托/事件/线程传参简单理解
    写了很多代码,但几乎都没写过委托/事件/线程传参方面应用的代码因此自己总很容易理解后又遗忘今天又重温了一下因此以最简单的方式的代码方式写下来帮助理解1.线程传参[简单......
  • swoole基础进阶之进程篇1 进程、线程、协程
    视频https://www.bilibili.com/video/BV1oJ411U7bc/或https://edu.51cto.com/center/course/lesson/index?id=412750......
  • 线程简介
    线程简介一、多任务现实中太多这样同时做多件事情的例子了,看起来是多个任务都在做,其实本质上我们的大脑在同一时间依旧只做了一件事情。二、多线程原来是一条车道,车......
  • 多线程
    packagecom.bkc.bpmp.modules.external.service;importjava.util.concurrent.*;importjava.util.Date;importjava.util.List;importjava.util.ArrayList;/***Java线程......
  • python 线程
    1.1线程的背景知识importthreading#导入线程相关的模块t=threading.current_thread()#返回当前线程print(t)#主线程执行print(t.getName())#线程名字print......
  • python5种线程锁
    # 线程安全线程安全是多线程或多进程编程中的一个概念,在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会......
  • python的多线程
    一、线程的概念线程是CPU分配资源的基本单位。当一程序开始运行,这个程序就变成了一个进程,而一个进程相当于一个或者多个线程。当没有多线程编程时,一个进程相当于一个主线程......
  • WPF 给 Pen 的 DashStyle 设置 0 0 的虚线数组将会让渲染线程消耗大量 CPU 资源
    给WPF的Pen的DashStyle属性设置00的虚线,在绘制几何图形时,绘制的几何图形的尺寸将关联渲染线程所使用的CPU资源。大约在周长大于500时,将可以从任务管理器上看......
  • WPF 应用启动过程同时启动多个 UI 线程且访问 ContentPresenter 可能让多个 UI 线程互
    在应用启动过程里,除了主UI线程之外,如果还多启动了新的UI线程,且此新的UI线程碰到ContentPresenter类型,那么将可能存在让新的UI线程和主UI线程互等。这是多线程......