Java线程:线程的同步-同步方法

2023-10-30

本文转载至:http://lavasoft.blog.51cto.com/62575/221914

Java线程:线程的同步-同步方法
 
线程的同步是保证多线程安全访问竞争资源的一种手段。
线程的同步是Java多线程编程的难点,往往开发者搞不清楚什么是竞争资源、什么时候需要考虑同步,怎么同步等等问题,当然,这些问题没有很明确的答案,但有些原则问题需要考虑,是否有竞争资源被同时改动的问题?
 
在本文之前,请参阅《Java线程:线程的同步与锁》,本文是在此基础上所写的。
 
对于同步,在具体的Java代码中需要完成一下两个操作:
把竞争访问的资源标识为private;
同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
当然这不是唯一控制并发安全的途径。
 
synchronized关键字使用说明
synchronized只能标记非抽象的方法,不能标识成员变量。
 
为了演示同步方法的使用,构建了一个信用卡账户,起初信用额为100w,然后模拟透支、存款等多个操作。显然银行账户User对象是个竞争资源,而多个并发操作的是账户方法oper(int x),当然应该在此方法上加上同步,并将账户的余额设为私有变量,禁止直接访问。

/** 
* Java线程:线程的同步 
* 
* @author leizhimin 2009-11-4 11:23:32 
*/ 
public class Test { 
        public static void main(String[] args) { 
                User u = new User("张三", 100); 
                MyThread t1 = new MyThread("线程A", u, 20); 
                MyThread t2 = new MyThread("线程B", u, -60); 
                MyThread t3 = new MyThread("线程C", u, -80); 
                MyThread t4 = new MyThread("线程D", u, -30); 
                MyThread t5 = new MyThread("线程E", u, 32); 
                MyThread t6 = new MyThread("线程F", u, 21); 

                t1.start(); 
                t2.start(); 
                t3.start(); 
                t4.start(); 
                t5.start(); 
                t6.start(); 
        } 
} 

class MyThread extends Thread { 
        private User u; 
        private int y = 0; 

        MyThread(String name, User u, int y) { 
                super(name); 
                this.u = u; 
                this.y = y; 
        } 

        public void run() { 
                u.oper(y); 
        } 
} 

class User { 
        private String code; 
        private int cash; 

        User(String code, int cash) { 
                this.code = code; 
                this.cash = cash; 
        } 

        public String getCode() { 
                return code; 
        } 

        public void setCode(String code) { 
                this.code = code; 
        } 

        /** 
         * 业务方法 
         * @param x 添加x万元 
         */ 
        public synchronized void oper(int x) { 
                try { 
                        Thread.sleep(10L); 
                        this.cash += x; 
                        System.out.println(Thread.currentThread().getName() + "运行结束,增加“" + x + "”,当前用户账户余额为:" + cash); 
                        Thread.sleep(10L); 
                } catch (InterruptedException e) { 
                        e.printStackTrace(); 
                } 
        } 

        @Override 
        public String toString() { 
                return "User{" + 
                                "code='" + code + '\'' + 
                                ", cash=" + cash + 
                                '}'; 
        } 
}


输出结果:

线程A运行结束,增加“20”,当前用户账户余额为:120 
线程F运行结束,增加“21”,当前用户账户余额为:141 
线程E运行结束,增加“32”,当前用户账户余额为:173 
线程C运行结束,增加“-80”,当前用户账户余额为:93 
线程B运行结束,增加“-60”,当前用户账户余额为:33 
线程D运行结束,增加“-30”,当前用户账户余额为:3 


反面教材,不同步的情况,也就是去掉oper(int x)方法的synchronized修饰符,然后运行程序,结果如下:

线程A运行结束,增加“20”,当前用户账户余额为:61 
线程D运行结束,增加“-30”,当前用户账户余额为:63 
线程B运行结束,增加“-60”,当前用户账户余额为:3 
线程F运行结束,增加“21”,当前用户账户余额为:61 
线程E运行结束,增加“32”,当前用户账户余额为:93 
线程C运行结束,增加“-80”,当前用户账户余额为:61 


很显然,上面的结果是错误的,导致错误的原因是多个线程并发访问了竞争资源u,并对u的属性做了改动。
 
可见同步的重要性。
 
 
注意:
通过前文可知,线程退出同步方法时将释放掉方法所属对象的锁,但还应该注意的是,同步方法中还可以使用特定的方法对线程进行调度。这些方法来自于java.lang.Object类。
void notify()    
                    唤醒在此对象监视器上等待的单个线程。    
void notifyAll()    
                    唤醒在此对象监视器上等待的所有线程。    
void wait()    
                    导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。    
void wait(long timeout)    
                    导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。    
void wait(long timeout, int nanos)    
                    导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量

结合以上方法,处理多线程同步与互斥问题非常重要,著名的生产者-消费者例子就是一个经典的例子,任何语言多线程必学的例子。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java线程:线程的同步-同步方法 的相关文章

  • Java线程:volatile关键字

    本文转载至 http lavasoft blog 51cto com 62575 222076 Java线程 volatile关键字 Java 语言包含两种内在的同步机制 同步块 或方法 和 volatile 变量 这两种机制的提出都是为了
  • Java 反射 与 主要API

    控制你的大脑 控制你的行为 你会得到更多 收获很多 文章目录 一 反射相关的主要API 二 代码例子演示 三 反射测试类 一 反射相关的主要API API 名称 代表含义 Java lang class 代表一个类 java lang re
  • (java基础知识)HashMap排序,Comparator接口详解

    对于List 可以调用Collections工具类的sort 方法 直接进行排序 HashMap 就没这么幸福了 其实 只要了解了Comparator这个接口之后 HashMap的排序也就不难了 无论是根据key 还是根据value排序 这
  • Java 父类 与子类之间的转换

    一 子类的实列化通过父类实现 代码正常 二 基于子类的实列化是通过父类实现 强制转换父类 代码正常 三 父类的实列化不能强制转换为子类 代码错误 提示 java lang ClassCastException 针对第三种情况 建议采用方案
  • java 清除字符串空格

    JAVA中去掉空格 1 String trim trim 是去掉首尾空格 2 str replace 去掉所有空格 包括首尾 中间 String str hell o String str2 str replaceAll System ou
  • Java线程:线程的同步-同步方法

    本文转载至 http lavasoft blog 51cto com 62575 221914 Java线程 线程的同步 同步方法 线程的同步是保证多线程安全访问竞争资源的一种手段 线程的同步是Java多线程编程的难点 往往开发者搞不清楚什
  • Java线程:线程的交互

    本文转载至 http lavasoft blog 51cto com 62575 99157 线程交互是比较复杂的问题 SCJP要求不很基础 给定一个场景 编写代码来恰当使用等待 通知和通知所有线程 一 线程交互的基础知识 SCJP所要求的
  • (java 功能篇)java 读取Propety配置文件

    java效果代码 源代码 package com rf test import java io IOException import java io InputStream import java util Properties publi
  • java 线程:概念与原理

    本文转载至 http lavasoft blog 51cto com 62575 99150 一 操作系统中线程和进程的概念 现在的操作系统是多任务操作系统 多线程是实现多任务的一种方式 进程是指一个内存中运行的应用程序 每个进程都有自己独
  • Java线程:线程栈模型与线程的变量

    本文转载至 http lavasoft blog 51cto com 62575 99152 要理解线程调度的原理 以及线程执行过程 必须理解线程栈模型 线程栈是指某时刻时内存中线程调度的栈信息 当前调用的方法总是位于栈顶 线程栈的内容是随
  • Java线程:新特征-障碍器

    本文转载至 http lavasoft blog 51cto com 62575 222738 Java5中 添加了障碍器类 为了适应一种新的设计需求 比如一个大型的任务 常常需要分配好多子任务去执行 只有当所有子任务都执行完成时候 才能执
  • Java线程:并发协作-死锁

    本文转载至 http lavasoft blog 51cto com 62575 222074 Java线程 并发协作 死锁 线程发生死锁可能性很小 即使看似可能发生死锁的代码 在运行时发生死锁的可能性也是小之又小 发生死锁的原因一般是两个
  • 线程管理之获取和设置线程信息

    获取和设置线程信息 Thread类的对象中保存了一些属性信息能够帮助我们来辨别每一个线程 知道它的状态 调整控制其优先级 这些属性是 ID 每个线程的独特标识 Name 线程的名称 Priority 线程对象的优先级 优先级别在1 10之间
  • Java 数组 初始化方式 和遍历方式

    Java 数组 初始化方式总结 第一种 静态初始化 所谓静态初始化 初始化时由程序员显式指定每个数组元素的初始值 有系统决定数组的长度 简单实例 String strArr 张三 李四 王五 第二种 动态初始化 所谓动态初始化 初始化时由程
  • 使用 IO 流 读取 本 地 文 件 (两种方式)

    使用IO 流读取本地文件 public class FileReadWrite public static void main String args FileReader fr null try 1 创建读取文件 fr new FileR
  • 代码质量保障第2讲:单元测试 - 浅谈单元测试

    代码质量保障第2讲 单元测试 浅谈单元测试 本文是代码质量保障第2讲 浅谈单元测试 单元测试 unit testing 是指对软件中的最小可测试单元进行检查和验证 这是基础 所以围绕着单元测试 我从网上搜集和总结了相关的概念 以助你完善体系
  • (java 基础知识) Java 安全套接字--javax.net.ssl

    有关SSL的原理和介绍在网上已经有不少 对于Java下使用keytool生成证书 配置SSL通信的教程也非常多 但如果我们不能够亲自动手做一个SSL Sever和SSL Client 可能就永远也不能深入地理解Java环境下 SSL的通信是
  • java并发包:生产者消费者模式

    本文转载至 http blog csdn net a910626 article details 51900974 生产者消费者模式是一个经典的多线程设计模式 它为多线程间的协作提供了良好的解决方案 在生产者消费者模式中 通常有两类线程 即
  • 线程管理之Thread类相关方法简介

    CurrentThread 静态方法 currentThread 方法可返回代码段正在被那个线程调用的信息 简单案列 打印main 方法 正在被那个线程调用 package com zzg thread import com zzg obj
  • java 多线程学习笔记之 线程实现(线程阻塞)

    java 实现线程方法主要分为两种方法 一种是继承 java lang Thread 另一种实现java lang Runnable接口 对于直接继承Thread 的类来说 代码大致框架是 public class MyThread ext

随机推荐

  • docker进阶笔记(高级版)

    1 mysql主从复制 mysql master 新建mysql master容器 docker run d p 3307 3306 privileged true v Users yaoqiang app data mysql maste
  • Unity:Quaternion类(四元数)

    Unity Quaternion 四元数 一 四元数理解 四元数左乘向量 表示将该向量按照四元数表示的角度旋转 例如 Vector3 point new Vector3 0 0 10 Vector3 newPoint Quaternion
  • 微信小程序中图片占满整个屏幕实现方法

    将body和html设置为100 这样我们就可以在他们的子元素中使用height 100 来使的我们的容器元素占满屏幕的高度啦 但是在微信小程序中 是没有dom对象的 根节点是page 使用page height 100 果然 是可行的 高
  • C/C++实现快速排序(两种方式)

    介绍 快速排序是对冒泡排序算法的一种改进 快速排序算法通过多次比较和交换来实现排序 流程如下 图片来自百度 实现 以下有两种实现方式 说是两种 其实就是在交换元素时具体细节上有点不同罢了 方式一 int Partition int A in
  • Spring的RestTemplate是什么东西?它有什么作用?

    RestTemplate是Spring提供的一个服务之间请求的工具 并且可以自动实现json的序列化和反序列化
  • pycharm导包不成功,如何清缓存,设置源目录

    pycharm导入本地包不成功 解决方法 1 清缓存 2 pycharm设置源目录
  • 中心化(又叫零均值化)和标准化(又叫归一化)

    一 中心化 又叫零均值化 和标准化 又叫归一化 概念及目的 1 在回归问题和一些机器学习算法中 以及训练神经网络的过程中 通常需要对原始数据进行中心化 Zero centered或者Mean subtraction subtraction表
  • pid双闭环matlab仿真,SPWM波控制单相逆变器双闭环PID调节器的Simulink建模与仿真

    随着电力行业的快速发展 逆变器的应用越来越广泛 逆变器的好坏会直接影响整个系统的逆变性能和带载能力 逆变器的控制目标是提高逆变器输出电压的稳态和动态性能 稳态性能主要是指输出电压的稳态精度和提高带不平衡负载的能力 动态性能主要是指输出电压的
  • 计算机网络复习-习题整理(三) 物理层

    1 对于带宽为4KHz的信道 若用8种不同的物理状态来表示数据 信噪比为30db 试问按奈奎斯特定理 最大限制的数据速率是多少 按香农定理最大限制的数据速率是多少 正确答案 按奈奎斯特定理 C 2W log2N N 8 W 4KHZ C 2
  • spring AOP实现后端日志操作记录功能

    一 引入配置文件
  • Numpy 数组复合排序——mX4列,根据多列组合排序

    Numpy 数组复合排序 mX4列 根据多列组合排序 一 Numpy 仅根据某列对 array mX4 整体排序用argsort import numpy as np data np array 1 5 2 4 10 9 6 8 4 5 2
  • 我的世界java版如何装mod_我的世界mod怎么安装图文教程

    我的世界mod怎么安装图文教程 如果你想在自己的机子上玩到好的地图或者建筑是需要mod 当然你也可以自己制作 但是今天主要介绍的是如何将别人的MOD移到自己的机子上去 我的世界mod资源 MOD安装 1 准备一个正常可用的解压缩软件 推荐7
  • finereport9.0破解版

    nereport9 0破解版 finereport10 0破解并发数 finereport授权注册 FineBI5 0破解lic 联系QQ 563471794 详细解密finereport9 0破解版中的报表执行过程 在报表开发工具Fine
  • Python小项目:利用CNN实现垃圾图片分类

    文章目录 1 前言 2 卷积神经网络 CNN 详解 2 1 CNN架构概述 2 1 1 卷积层 2 1 2 池化层 2 1 3 全连接层 2 2 CNN训练过程 2 3 CNN在垃圾图片分类中的应用 3 代码详解 3 1 导入必要的库 3
  • 将IDEA MAVEN项目打包成jar包的通用方法

    1 找到左上角File gt Project Structure 点击 中文 文件 gt 项目结构 2 在弹出的界面中 点击Artifacts 中文 工件 点击内置页面的左上角的 号 选中第一个的第二个 点击 3 在弹出的界面 选择运行的类
  • string和long转换

    String转Long的两种方法 1 Long valueOf String 返回Long包装类型 2 Long parseLong String 返回long基本数据类型 String类型时间转Long类型时间戳 String time
  • 剑指 Offer 45. 把数组排成最小的数—一道字符串比较的问题

    写法一 class Solution public String minNumber int nums 如果为空 if nums null nums length 0 return null 创建字符数组 String strs new S
  • 【大数据模型】让chatgpt为开发增速(开发专用提示词)

    汝之观览 吾之幸也 本文主要聊聊怎样才能更好的使用提示词 给开发提速 大大缩减我们的开发时间 比如在开发中使用生成表结构脚本的提示词 生成代码的提示词等等 一 准备 本文主要根据Claude进行演示 关于如何使用Claude技术 主要是免费
  • 2023校招荣耀笔试

    大端小端字符串转换 主要是卡9的倍数这进行判断 这个很简单 直接做 会议室最长使用时间 这个和之前的遇到i的会议室的题目看似相同 又不一样 之前那种可以转换成公交车上下车问题 这个我尝试相同思路去做感觉挺麻烦的 然后我就想着用动态规划做 鼓
  • Java线程:线程的同步-同步方法

    本文转载至 http lavasoft blog 51cto com 62575 221914 Java线程 线程的同步 同步方法 线程的同步是保证多线程安全访问竞争资源的一种手段 线程的同步是Java多线程编程的难点 往往开发者搞不清楚什