java实现线程同步的方法_Java实现线程同步方法及原理详解
一、概述
无论是什么语言,在多线程编程中,常常会遇到多个线同时操作程某个变量(读/写),如果读/写不同步,则会造成不符合预期的结果。
例如:线程A和线程B并发运行,都操作变量X,若线程A对变量X进行赋上一个新值,线程B仍然使用变量X之前的值,很明显线程B使用的X不是我们想要的值了。
Java提供了三种机制,解决上述问题,实现线程同步:
同步代码块
synchronized(锁对象){
// 这里添加受保护的数据操作
}
同步方法
静态同步方法:synchronized修饰的静态方法,它的同步锁是当前方法所在类的字节码对象
public static synchronized void staticMethod(){
}
非静态同步方法:synchronized修饰的非静态方法,它的同步锁即为this
public synchronize void method(){
}
锁机制
// 以可重入锁举例
Lock lock = new ReentrantLock(/*fail*/);
// fail:
// true表示使用公平锁,即线程等待拿到锁的时间越久,越容易拿到锁
// false表示使用非公平锁,线程拿到锁全靠运气。。。cpu时间片轮到哪个线程,哪个线程就能获取锁
lock.lock();
// 这里添加受保护的数据操作
lock.unlock();
个人理解:其实无论哪种机制实现线程同步,本质上都是加锁->操作数据->解锁的过程。同步代码块是针对{}中,同步方法是针对整个方法。其ReentrantLock类提供的lock和unlock和C++的std::mutex提供lock和unlock类似
二、测试用例
同步代码块测试类
package base.synchronize;
public class SynchronizeBlock implements Runnable {
private int num = 100;
@Override
public void run() {
while (num > 1) {
synchronized (this) {
// 同步代码块,只有拿到锁,才有cpu执行权
System.out.println("Thread ID:" + Thread.currentThread().getId() + "---num:" + num);
num--;
}
}
System.out.println("Thread ID:" + Thread.currentThread().getId() + " exit");
}
}
同步方法测试类
package base.synchronize;
public class SynchronizeMethod implements Runnable {
private int num = 100;
public static int staticNum = 100;
boolean useStaticMethod;
public SynchronizeMethod(boolean useStaticMethodToTest) {
this.useStaticMethod = useStaticMethodToTest;
}
// 对于非静态方法,同步锁对象即this
public synchronized void method() {
System.out.println("Thread ID:" + Thread.currentThread().getId() + "---num:" + num);
num--;
}
// 对于静态方法,同步锁对象是当前方法所在类的字节码对象
public synchronized static void staticMethod() {
System.out.println("Static Method Thread ID:" + Thread.currentThread().getId() + "---num:" + staticNum);
staticNum--;
}
@Override
public void run() {
if (useStaticMethod) { // 测试静态同步方法
while (staticNum > 1) {
staticMethod();
}
}else{ // 测试非静态同步方法
while (num > 1){
method();
}
}
System.out.println("Thread ID:" + Thread.currentThread().getId() + " exit");
}
}
ReentrantLock测试类
package base.synchronize;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SynchronizeLock implements Runnable {
private Lock lock = null;
private int num = 100;
public SynchronizeLock(boolean fair){
lock = new ReentrantLock(fair); // 可重入锁
}
@Override
public void run() {
while (num > 1) {
try {
lock.lock();
System.out.println("Thread ID:" + Thread.currentThread().getId() + "---num:" + num);
num--;
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
System.out.println("Thread ID:" + Thread.currentThread().getId() + " exit");
}
}
测试三种机制的Demo
package base.synchronize;
public class Demo {
public static void main(String[] args) {
synchronizeBlockTest(); // 同步代码块
synchronizeMethodTest(); // 同步非静态方法
synchronizeStaticMethodTest(); // 同步静态方法
synchronizeLockTest(); // 可重入锁机制
}
public static void synchronizeBlockTest(){
Runnable run = new SynchronizeBlock();
for(int i = 0; i < 3; i++){
new Thread(run).start();
}
}
public static void synchronizeMethodTest(){
Runnable run = new SynchronizeMethod(false);
for(int i = 0; i < 3; i++){
new Thread(run).start();
}
}
public static void synchronizeStaticMethodTest() {
Runnable run = new SynchronizeMethod(true);
for(int i = 0; i < 3; i++){
new Thread(run).start();
}
}
public static void synchronizeLockTest(){
Runnable run = new SynchronizeLock(false); // true:使用公平锁 false:使用非公平锁
for(int i = 0; i < 3; i++){
new Thread(run).start();
}
}
}
无论哪种机制,都得到预期的效果,打印100-0
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
java实现线程同步的方法_Java实现线程同步方法及原理详解相关推荐
- java mod 函数的使用方法_Java中 % 与Math.floorMod() 区别详解
%为取余(rem),Math.floorMod()为取模(mod) 取余取模有什么区别呢? 对于整型数a,b来说,取模运算或者取余运算的方法都是: 1.求 整数商: c = a/b; 2.计算模或者余 ...
- java 线程同步的方法_Java多线程同步方法
Java多线程同步方法 package com.wkcto.intrinsiclock; /** * synchronized同步实例方法 * 把整个方法体作为同步代码块 * 默认的锁对象是this对 ...
- java中math的方法_Java中Math类常用方法代码详解
近期用到四舍五入想到以前整理了一点,就顺便重新整理好经常见到的一些四舍五入,后续遇到常用也会直接在这篇文章更新... public class Demo{ public static void mai ...
- java黄金分割数的解题思路_java 实现黄金分割数的示例详解
黄金分割数 0.618 与美学有重要的关系.舞台上报幕员所站的位置大约就是舞台宽度的 0.618 处, 墙上的画像一般也挂在房间高度的 0.618 处,甚至股票的波动据说也能找到 0.618 的影子- ...
- java线程安全的方法_Java实现线程安全的方式
多线程环境中如何保证线程安全?java可以实现线程安全的方式归纳如下: 1.使用synchronized关键字 synchronized关键字可以修饰方法和代码块,它的语义是保证同一段代码同一时间只能 ...
- java的循环控制结构有哪些_java中的控制结构(if,循环)详解
1 说明JAVA语言中三种控制循环结构的代码形式(其他 1. while(condition){ statements; } 其中,condition是任何布尔表达式,其返回值为true 或 fals ...
- java 判断端口是否被占用_java检测端口是否被占用详解
Java可以通过Socket类来检测端口是否被占用: import java.net.*; import java.io.*; public class Main { public static vo ...
- cordova监听事件中调用其他方法_Laravel模型事件的实现原理详解
模型事件在 Laravel 的世界中,你对 Eloquent 大多数操作都会或多或少的触发一些模型事件,下面这篇文章主要给大家介绍了关于Laravel模型事件的实现原理,文中通过示例代码介绍的非常详细 ...
- Java中高级核心知识全面解析——常用框架(SpringMVC-工作原理详解)
一.先来看一下什么是 MVC 模式 MVC 是一种设计模式. MVC 的原理图如下: 二.SpringMVC 简单介绍 SpringMVC 框架是以请求为驱动,围绕 Servlet 设计,将请求发给控 ...
最新文章
- js 变量、函数提升
- Kira同学:斩获百度校招提前批offer备战细节全揭秘
- Java Hashtable hashCode()方法及示例
- POJ 1380 坐标旋转
- 织梦留言板guestbook.htm加入头部导航
- Y2K Accounting Bug(poj2586)
- Introducing DataFrames in Apache Spark for Large Scale Data Science(中英双语)
- sklearn学习 6.聚类算法K-Means
- matches php,PHP 正则表达式 推荐
- Linux下安装Mysql详解
- Python基于共现提取《釜山行》人物关系
- c语言用函数写大小写转换,C语言实现大小写转换的三种方法
- 西游记中托塔李天王的三个儿子,一个女儿和一个干女儿
- 【产业互联网周报】容联云下周纽交所挂牌;声网Agora因Clubhouse股价周内涨超30%;贝索斯将卸任亚马逊CEO...
- 云​大数据和计算技术周报(第43期)
- 获取Shell命令执行错误结果
- 计算机内部线有,电脑主机内部有几根线?分别叫什么?
- 就决定是你啦!苏菲婆5! —— 谈谈我对Surface Pro 5的使用体验以及各种骚操作
- JavaScript -函数式编程
- 兰大计算机考试2020年5月在线考试答案,《计算机组成原理》兰大2020年9月在线考核试题题目及答案...
热门文章
- jni android 参数 字符串 jstring,2.4.5 jstring介绍
- QIIME 2教程. 14数据评估和质控q2-quality-control(2021.2)
- QIIME 2用户文档. 9数据导入Importing data(2019.7)
- Python使用matplotlib可视化分布点图、自定义设置分布点图的中位数数据点的颜色(Distributed Dot Plot)
- pandas使用query函数查询dataframe指定数据列的内容(数值)包含在特定列表中的数据行(select rows which column values contain in list)
- R语言使用scales包的hue_pal函数获取ggplot2任何级别的离散色码、使用scales包的hue_pal函数获取ggplot2任何级别的反序(reverse)离散色码
- R语言构建文本分类模型并使用LIME进行模型解释实战:文本数据预处理、构建词袋模型、构建xgboost文本分类模型、基于文本训练数据以及模型构建LIME解释器解释多个测试语料的预测结果并可视化
- R语言泊松分布函数Poisson Distribution(dpois, ppois, qpois rpois)实战
- python使用fpdf2包和pdfrw报包新内容添加到已有的PDF页面上
- Error in install.packages : cannot remove prior installation of package