【Java多线程】多线程同步——对“synchronized”关键字的简单理解

深入理解Java多线程同步机制 本文还有配套的精品资源,点击获取 简介:在Java中,多线程同步是确保并发操作中数据一致性和程序正确性的关键。本课程将详细探讨多线程同步的概念,解释线程的定义和创建方式,并介绍Java提供的多种同步机制,如synchronized关键字、volatile关键字、Lock接口与ReentrantLock类、Atomic类、ThreadLocal、Condition接口以及Co... 阅读详情

既然一个进程中可以有多个线程,并且多个线程共享资源,那么,由谁来管理这些个共享的资源,以至于不被各个线程争抢呢?

什么是多线程安全

线程安全的定义:

  • 对全局变量或者静态变量,同时都有读、写操作,从而造成变量数据紊乱,产生错误。

发生线程安全的原因:

  1. 线程安全问题都是由全局变量及静态变量引起的。
  2. 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;
  3. 若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

解决线程安全的方案:

  • Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,
  • 第一个是 JVM 实现的 synchronized(内部锁),
  • 而另一个是 JDK1.5 实现的 ReentrantLock(重入锁)。

synchronized实现多线程互斥

对synchronized的理解:

  1. 是Java 中的关键字,synchronized 是内置的语言实现;
  2. synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;

synchronized特性:

  • synchronized: 同步(锁,又称为内部锁,因为它是用Java关键字实现的),可以修饰代码块和方法,能够保证在同一时刻最多只有一个线程执行该段代码。
  • 一旦使用synchronized,多线程执行起来就慢了。因为每次执行“锁中的代码时”,都要检查有没有线程正在占用这段代码。
  • 如果被占用了,则要等待这个占用线程执行完毕,才有机会执行该线程。

synchronized使用的三种方式:

  1. 修饰方法:对当前对象加锁,进入同步代码前要获得当前对象的锁。
  2. 修饰静态方法:给当前类加锁,会作用于类的所有对象实例。
  • 因为静态成员不属于任何一个实例对象,是类成员( static 表明这是该类的一个静态资源,不管new了多少个对象,只有一份)。
  • 所以如果一个线程A调用一个实例对象的非静态 synchronized 方法,而线程B需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁。
  1. 修饰代码块:指定加锁对象。

总结: synchronized 关键字加到 static 静态方法和 synchronized(class)代码块上都是是给 Class 类上锁。synchronized 关键字加到实例方法上是给对象实例上锁。

同步代码块

同步代码块的格式:

	synchronized(锁对象){ //锁对象是所有对象都能共享的对象
	……
	}

注意: 它只作用于同一个对象,如果调用两个对象上的同步代码块,就不会进行同步。

理解synchronized如何加锁对象


public class ThreadDemo {
	public static void main(String[] args) {
		MyMultiThread mmt = new MyMultiThread();
		Thread t1 = new Thread(mmt);
		Thread t2 = new Thread(mmt);
		
		t1.setName("线程1");
		t2.setName("线程2");
		
		t1.start();
		t2.start();
	}
}

class MyMultiThread implements Runnable {
	private Object obj = new Object();; //synchronized加锁的对象时obj
	private int num = 100;
	
	@Override
	public void run() {
		while(true) {
			synchronized(obj) { //加锁obj对象,一旦有线程获得这个对象,其他线程试图获取它时将阻塞!
				if(num>0) {
					System.out.println(Thread.currentThread().getName()+"执行减法!"+num--);
				} else {
					break;
				}
			}
		}
	}
}

同步代码块实例

问题: 实现火车站窗口卖票功能
1, 火车站卖票窗口有3个窗口,同时卖票;
2, 火车站有一定数量的火车票,每售出一张数量减一;当火车票的数量小于1的时候,停止售票;

用同步代码块实现卖火车票:

public class Main {
	public static void main(String[] args) {
		// 创建线程对象
		TicketThread tt = new TicketThread();

		Thread t = new Thread(tt);
		t.setName("窗口1");
		Thread t2 = new Thread(tt);
		t2.setName("窗口2");
		Thread t3 = new Thread(tt);
		t3.setName("窗口3");

		// 启动线程对象
		t.start();
		t2.start();
		t3.start();
	}
}

class TicketThread implements Runnable {
	int tickets = 100; // 火车票
	Object obj = new Object();
	@Override
	public void run() {
		//出售火车票
		while(true) {
			synchronized (obj) {
				if(tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					System.out.println(Thread.currentThread().getName() + ":出售" +tickets--);
				}
			}
		}
	}
}

同步方法

同步方法的格式:

修饰符 synchronized 返回类型 方法名(参数列表) {
	方法体
}

**同步方法: **

  1. 使用关键字synchronized修饰的方法,一旦被一个线程访问,则整个方法全部锁住,其他线程则无法访问。
  2. 普通方法中的锁是this对象;
  3. 它和同步代码块一样,作用于同一个对象。

用同步方法实现卖火车票

public class Main {
	public static void main(String[] args) {
		// 创建线程对象
		TicketThread tt = new TicketThread();

		Thread t = new Thread(tt);
		t.setName("窗口1");
		Thread t2 = new Thread(tt);
		t2.setName("窗口2");
		Thread t3 = new Thread(tt);
		t3.setName("窗口3");

		// 启动线程对象
		t.start();
		t2.start();
		t3.start();
	}
}

class TicketThread implements Runnable {
	int tickets = 100; // 火车票
	Object obj = new Object();
	@Override
	public void run() {
		//出售火车票
		while(true) {
			method2();
		}
	}
	
	private synchronized void method2() { //同步方法的锁对象就是this对象
		if (tickets > 0) {
			try {
				Thread.sleep(100); //线程休眠
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + ":" + tickets--);
		}
	}
}

同步静态方法

同步静态方法的格式:

//同步一个静态方法:
修饰符 synchronized static 返回类型 方法名(参数列表) {
方法体
}

特性:

  1. static方法中的锁是类本身的字节码文件,即“类名.class”;
  2. 作用于整个类。
  3. 也就是说,这个类的所有实例都被加上同一把锁。

用同步static方法实现卖火车票

public class Main {
	public static void main(String[] args) {
		// 创建线程对象
		TicketThread tt = new TicketThread();

		Thread t = new Thread(tt);
		t.setName("窗口1");
		Thread t2 = new Thread(tt);
		t2.setName("窗口2");
		Thread t3 = new Thread(tt);
		t3.setName("窗口3");

		// 启动线程对象
		t.start();
		t2.start();
		t3.start();
	}
}

class TicketThread implements Runnable {
	static int tickets = 100; // 火车票
	Object obj = new Object();
	@Override
	public void run() {
		while(true) {//出售火车票
			method2();
		}
	}
	
	private static synchronized void method2() { //静态方法中,锁是本类自己,即“本类名.class”
		if (tickets > 0) {
			try {
				Thread.sleep(100); //线程休眠
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + ":" + tickets--);
		}
	}
}

JDK1.6之后对锁的优化

由于synchronized关键字对于多线程的同步的支持性不是很友好。所以,在JDK1.6 对锁的实现引入了大量的优化,如偏向锁、轻量级锁、自旋锁、适应性自旋锁、锁消除、锁粗化等技术来减少锁操作的开销。

具体JDK1.6对锁做了哪些优化和升级,请关注本站的后续文章!


工业质检实战:如何用MVTec AD数据集训练你的第一个无监督异常检测模型 本文提供了一份基于MVTec AD数据集的工业质检实战指南,详细介绍了如何从零开始训练一个无监督异常检测模型。内容涵盖数据预处理、模型架构选型(如CAE、GAN与特征字典方法)、特征提取、损失函数设计以及关键的阈值确定与后处理流程,旨在帮助工程师快速掌握将AI技术落地于实际产线质检的核心步骤与调参经验。 阅读详情

相关推荐

A Super-Resolution Imaging Method for Forward-Looking Scanning Radar Based on Improved TV论文阅读

具体而言,作者提出了一种改进的总变差(Improved Total Variation, ITV)方法,通过引入。论文旨在解决前视扫描雷达(Forward-Looking Scanning Radar)超分辨率成像中传统。(Batch Processing),以增强图像边缘特征的保留能力,并提升计算效率。论文的核心创新点在于对传统TV正则化的邻域梯度计算进行扩展,提出。ITV剖面(图3d)在噪声下仍保持矩形边缘,仅存。​(公式10):实现稀疏约束。),抑制远端单元贡献。(幅度远低于目标)。

yangqoor的博客 1239

【速看】一文清明讲明白线程同步关键字synchronized

synchronized 关键字是java的保留字,synchronized 关键字保障了原子性、可见性和有序性。 在java中,线程同步使用最多的方法是使用synchronized关键字,使用synchronized(synchObject)调用相当于获取synchObject的内置锁,对临界区代码段进行排他性保护。synchronized块是java提供的一种原子性内置锁,java中的每个对象都可以把它当做一个同步锁来使用,这些java内置的使用者看不到的锁被称为内部锁,也叫做监视器锁。

唐欢 635

STM32H743必要外围电路分析

写在前面:这篇博客是我第一次绘制STM32最小系统板的过程记录。 2020-1-11 BOOT STM32采用ARM内核,和ARM处理器一样,都有专门的boot脚决定单片机从何处启动。 在官方数据手册的第105页,我们可以看到 系统复位后,在SYSTICK的第四个上升沿锁存BOOT引脚的值,复位后,BOOT引脚可以由用户自由配置而不会影响系统正常运行。 BOOT引脚决定了自举存储器地址,当BO...

Cui_Hongwei的博客 1万+

synchronized实现线程同步的用法和实现原理

作用和用法 在多线程对共享资源进行并发访问方面,JDK提供了synchronized关键字来进行线程同步,实现多线程并发访问的线程安全。synchronized的作用主要体现在三个方面:(1)确保线程互斥地访问同步代码;(2)保证共享变量的线程可见性;(3)禁止指令重排。其中(2)和(3)相当于volatile关键字的作用。 sychronized可以用在(1)静态方法,(2)普通成员方法...

源码之下,了无秘密 6134

可信数据空间:可信空间、区域功能节点、业务功能节点、连接器的关联关系

可信数据空间通过分层架构实现安全数据共享:可信空间作为顶层制定全局规则;区域功能节点协调辖区内功能节点协作;功能节点提供具体数据服务;连接器作为唯一通信通道确保安全交互。系统采用"规则自上而下约束,数据自下而上流动"机制,通过分层治理和标准化连接,在保证数据主权的同时实现跨域协作,具有策略分级执行、去中心化治理等特性,支持灵活扩展业务场景。

友莘居士的博客 1685

Plant Simulation新手入门:5步搞定生产线物流仿真(附模型库使用技巧)

本文为Plant Simulation新手提供了从零开始构建生产线物流仿真的五步入门指南。通过理念重塑、流程规划、对象连接、参数设置到数据分析的完整流程,帮助用户快速掌握这一强大仿真工具的核心逻辑。文章特别强调了模型库的高效使用技巧,助力工程师在虚拟环境中精准模拟和优化生产系统,提升规划效率。

efc123456的博客 333

多线程同步实现原理、同步函数、同步代码块、静态同步函数(关键字synchronized)的详解。

多线程同步实现原理、同步函数、同步代码块、静态同步函数(关键字synchronized)的详解。 在说明同步函数和同步代码快、静态同步函数之前我们先想想: 什么是线程同步? 多线程为什么需要实现同步? 实现同步的原理是什么? 举个栗子:需求现在有100章火车票,有两个窗口同时抢火车票(相当于两个线程),请使用多线程模拟抢票效果。 代码如下:(此段代码非...

AE86-打破常规的博客 573

栅极驱动电路设计(一)

SiC驱动电路设计需满足更高标准,重点包括:驱动电压需18~20V开通、-3~-5V关断;栅极电阻优选5~10Ω以平衡开关性能与可靠性;必须集成欠压保护(阈值11~15V)和快速短路保护。多电平驱动控制通过动态调节栅压和驱动强度优化性能,如前期弱驱动抑制振荡,后期强驱动降低损耗。以NCE120ED65VTP4为例,栅压从18V提升至20V可使导通损耗降低15%。相比传统方案,有源驱动(含数字分段和模拟闭环控制)能更灵活地提升开关速度与效率。

嵌入式老牛的博客 449

多线程同步synchronized详解01

t1和t2 异步编程模型:t1线程执行t1的,t2线程执行t2的,两个线程之间谁也不等谁 同步编程模型:t1线程和t2线程执行,当t1线程必须等t2线程执行结束之后,t1线程才能执行 什么时候要同步呢?为什么要引入线程同步呢? 1.为了数据的安全,尽管应用程序的使用率降低,但是为了数据的安全,必须加入线程同步机制,线程同步机制使程序变成了(等同)单线程 2.什么条件下要使用线程同步? 第一,必须是...

qq_42895153的博客 175

LIS2DH三轴加速度传感器原理图设计,已量产(加速度传感器)

最近在做一款可穿戴设备原型时,选了 LIS2DH 这款加速度计 —— 比起之前常用的 ADXL345,它在低功耗和稳定性上的优化刚好戳中了可穿戴设备 “续航 + 可靠” 的核心需求。下面结合这次画的原理图,聊聊这个小模块的硬件设计细节。

不脱发的程序猿 388

后仿真中《SDF反标必懂连载篇》之 探究 SDF延迟精度 与 timescale 精度问题

本篇文章,同样属于后仿真中的SDF反标系列文章内容之一。今天,将前仿真中的timescale 和 后仿真中 timescale+sdf 延迟数据,进行贯通讲解。不要忽视这部分内容,因为后仿真的成功准确与否,时间精度问题,很重要。为什么?接下来一一讲解。

那么菜的博客 2310

java为什么引入进程和线程_为什么要引入进程

为了提高计算机系统的效率.增强计算机系统内各种硬件的并行操作能力.操作系统要求程序结构必须适应并发处理的需要.为此引入了进程的概念。进程是操作系统的核心,所有基于多道程序设计的操作系统都建立在进程的概念之上。目前的计算机系统均提供了多任务并行环境.无论是应用程序还是系统程序.都需要针对每一个任务创建相应的进程。进程是设计和分析操作系统的有力工具。然而不同的进程之间.即使是具有家族联系的父子进程.都...

weixin_39564527的博客 404

Qt入门教程【Core篇】singal and slot信号与槽

Qt中信号与槽singal and slot

小鱼酱的博客 2449

Java 关键字:synchronized详解

synchronized 是 Java 中用于实现线程同步的关键字,它提供了一种简单且有效的方式来控制多个线程对共享资源的访问。 synchronized 的作用是确保在同一时刻只有一个线程可以进入被 synchronized 修饰的代码块或方法,从而避免多个线程同时修改共享数据而引发的数据不一致性和并发访问问题。

唯有努力,方可自信! 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

深入理解 java synchronized 关键字

synchronized 这个关键字的重要性不言而喻,几乎可以说是并发、多线程必须会问到的关键字了。synchronized 会涉及到锁、升级降级操作、锁的撤销、对象头等。所以理解 synchronized 非常重要,本篇文章就带你从 synchronized 的基本用法、再到 synchronized 的深入理解,对象头等,为你揭开 synchronized 的面纱。

在技术的广袤天地里,本博客如精准罗盘。剖析前沿科技,深掘代码奥秘,以精炼笔触,带您穿越复杂技术迷宫,速达知识彼岸。 2463

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

深入理解 Java 中的 synchronized 关键字

目录1.基本概念什么是 synchronized? 可重入性2. 使用场景2.1 实例方法同步2.2 静态方法同步 2.3 代码块同步 3.锁机制3.1 对象锁 vs 类锁3.2 锁升级机制 3.3 自适应自旋锁自旋锁自适应自旋锁3.4 锁消除与锁粗化4.注意事项 4.1 避免过度同步4.2 理解锁的升级过程4.3 注意死锁问题4.4 考虑使用更高级别的并发工具在多线程编程中,确保数据的一致性和正确性是至关重要的。Java 提供了多种机制来实现这一点,其中最基础和常用的便是 关键字。本文将详细介绍 的各

m0_74750751的博客 2573

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

深入理解Java中的synchronized关键字

synchronized的详细讲解和底层实现,以及synchronized的同步机制,synchronized的重入和synchronized的异常演示

weixin_74268571的博客 1859

[Java中的多线程同步深入理解synchronized关键字的工作原理]

synchronized关键字是Java线程同步的基石。它通过对象内部监视器锁(Monitor)来实现互斥访问,并借助JVM的锁升级优化策略(偏向锁、轻量级锁、重量级锁)来有效平衡性能与线程安全的需求。理解其从语法语义到JVM底层实现的完整工作机制,是每一位Java开发者掌握并发编程、构建高性能高可靠性应用的必备知识。

f3051709的博客 703

对于Java中synchronized关键字的简单理解

对于Java中synchronized关键字的简单理解Synchronized关键字对象锁实现对象锁的几种方式类锁实现类锁的几种方式Object.wait()和Object.notify()Object.wait()Object.notify()三线程打印ABC Synchronized关键字 对象锁 作用于实例对应的内存位置。 一个实例一把锁,多个实例多把锁; 对象锁是针对一个实例(instance)的,它是在该实例对应的某个内存位置声明一个标识,记录该实例拥有锁,所以它只会锁住当前的实例, 而不会对当前

CaptainCats的博客 859

深入剖析Java多线程同步:synchronized关键字与哲学家就餐问题实战指南

大家好!今天让我们一起揭开Java多线程同步中的神秘面纱,特别是那个至关重要的关键字——synchronized。我们将从多线程的基础知识开始,逐步深入理解synchronized的工作原理,并通过一些生活化的例子帮助大家更好地消化这些概念。synchronized关键字帮助我们在多线程环境中维持数据的一致性和正确性,防止了竞态条件的发生。然而,过度或不当使用synchronized可能导致性能下降,比如过多的线程争抢同一把锁可能会造成“线程饥饿”或“活锁”等问题。

Z__10的博客 1258

Java线程同步中关键字synchronized简述

Java线程同步中关键字synchronized简述 一、作用: synchronized关键字通过修饰一个方法或者声明一个代码块,从而产生一个同步对象锁以及对应的同步代码块。每当有线程要对该同步代码块进行访问时,线程就会首先尝试去获取该对象锁,并在成功获取到对象锁后,对该同步代码块进行正常访问,在同步代码块访问过程中,线程会一直持有该对象锁直到同步代码块访问完毕才会释放。在上

什么乱七八糟的 4363

Java——多线程高并发系列之synchronized关键字

Java——多线程高并发系列之synchronized关键字

贝尔摩德苦艾酒 7353

java synchronized关键字以及对线程锁的理解

参考了2篇文章:  http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html http://www.cnblogs.com/benshan/p/3551987.html  Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。 一、当两个并发线程

eclipse_c 的专栏 1210

如何使用java synchronized进行线程同步

这篇文章从网上找到的,作者是谁不详,因为到处都是转帖。看了之后,解开了我对synchronized的一些疑问,同时也验证了我之前的理解是正确的,记录下来。 在java编程思想中对synchronized的一点解释:1、synchronized关键字的作用域有二种: 1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的s

soartju的专栏 2万+

理解synchronized关键字

当JVM执行到monitorexit指令时,_count-1,当锁计数器为0时,_Owner恢复为null,表示该锁被释放了,如果_EntryList非空,那么通知_EntryList中所有阻塞的线程,去竞争然后成为下一个_Owner。偏向锁只有遇到其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程不会主动去释放偏向锁。偏向锁 -> 轻量级锁:当A线程持有偏向锁时,此时B线程通过CAS自旋的方式去竞争锁,如果竞争成功修改偏向锁的线程ID依旧是偏向锁,否则锁会升级为轻量级锁。

小红的布丁的博客 1019

synchronized的简单理解

synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。它能够保证在同一时刻,被修饰的代码块或方法只会有一个线程执行,以达到保证并发安全的效果。原子性:确保线程互斥地访问同步代码;可见性:保证共享变量的修改能够及时可见;有序性:有效解决重排序问题。原子性"表示一个操作是不可分割的,要么成功执行,要么完全不执行。通常与线程同步相关,可以确保多个线程同时对共享变量进行读写时不会产生竞争条件和数据冲突。可见性。

沉淀所学,分享所思,让热爱与成长同行。商务记录AI实战经验,助力开发者快速成长。 热爱AI,希望做出有影响力的技术成果。 技术点亮生活,分享连接价值与机会。 专注AI落地实战,陪你走好技术每一步。 1万+
上一篇: 【Java多线程】快速入门Java的并发机制
下一篇: 【Java集合】逻辑结构超强、表达十分清晰的“Collection接口”及“List接口、Set接口”解析
ALGO阿狗
博客等级 码龄9年 64粉丝 149原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值