线程安全性 - 原子性 - 锁 synchronize

原子性 - 锁

原子性:互斥性。能保证同一时刻只有一个线程操作的,除了atomic包内的类,另个锁。

锁:

synchronized, 锁关键字,依赖jvm实现,这个关键字作用对象的作用范围内,同一时刻只能有一个线程操作的,

Lock:依赖特殊的cpu指令,代码实现,ReentrantLock

在这里插入图片描述

synchronized

synchronized同步锁,修饰4中对象
在这里插入图片描述

(1)修饰一个代码块,被修饰的范围叫做同步语句块,作用于调用对象,同一个对象调用是互斥的;

代码演示:

package com.mmall.concurrency.sync;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * @Author: wn
 * @Description: synchronized ,
 * @Date: Created in 2019/1/12 15:05
 */
@Slf4j
public class SynchronizedExample1 {

	// 修饰一个代码块,被修饰的范围叫做同步语句块,作用于调用对象
	public void test1() {
		synchronized (this) {
			for (int i = 0; i < 10; i++) {
				log.info("test1 {}", i);
			}
		}
	}

	// 修饰一个方法,,被修饰的范围叫做同步方法,作用于调用对象
	public synchronized void test2() {
		for (int i = 0; i < 10; i++) {
			log.info("test2 {}", i);
		}
	}

	public static void main(String[] args) {
		SynchronizedExample1 example1 = new SynchronizedExample1();
		SynchronizedExample1 example2 = new SynchronizedExample1();
		ExecutorService executorService = new ThreadPoolExecutor(2, 5, 3000,
				TimeUnit.MINUTES, new LinkedBlockingDeque<>(), new ThreadPoolExecutor.AbortPolicy());
//		log.info("修饰一个代码块,被修饰的范围叫做同步语句块,作用于调用对象,同一个对象调用是互斥的:");
//		executorService.execute(() -> {
//			example1.test1();
//		});
//		executorService.execute(() -> {
//			example1.test1();
//		});

		log.info("修饰一个方法,,被修饰的范围叫做同步方法,作用于调用对象,同一个对象调用是互斥的:");
		executorService.execute(() -> {
			example1.test2();
		});
		executorService.execute(() -> {
			example1.test2();
		});

//		log.info("调用不同的代码块,各自执行,互不影响");
//		executorService.execute(() -> {
//			example1.test1(1);
//		});
//		executorService.execute(() -> {
//			example2.test2(2);
//		});
	}
}

在这里插入图片描述

执行结果:
在这里插入图片描述

(2) 修饰一个方法,,被修饰的范围叫做同步方法,作用于调用对象,同一个对象调用是互斥的

在这里插入图片描述

执行结果:
在这里插入图片描述

(3)修饰一个类,作用对象是类的所有对象

在这里插入图片描述
运行结果:
在这里插入图片描述

(4)修饰一个静态方法,被修饰的范围叫做静态同步方法,作用对象是类的所有对象

在这里插入图片描述

运行结果:

在这里插入图片描述

synchronize 实现计数器

在这里插入图片描述

执行结果:
5000

原子性 - 对比 锁区别

在这里插入图片描述

synchronize :不可中断,一旦执行到同步代码时,就必须执行完,适合竞争不激烈的情况,可读性较好,当竞争很激烈时,synchronize 的性能下降非常快

Lock:可中断,调用unlock()可以中断线程执行,竞争激烈时保持常态,

atomic : 竞争激烈时也能维持常态,比Lock 性能好,缺点就是只能同步一个值

### Java `synchronized` 机制原理深入分析 #### 1. 的基本概念 在Java中,`synchronized` 是一种用于实现线程同步的关键字。它的主要作用是确保多个线程在访问共享资源时不会发生冲突[^3]。`synchronized` 的实现依赖于对象头中的 `Mark Word` 和 `Monitor`。 - **对象头**:每个Java对象都有一个对象头,其中包含 `Mark Word` 和类元数据地址。`Mark Word` 存储了的状态、线程ID等信息[^5]。 - **Monitor**:`Monitor` 是一种同步工具,它保证同一时刻只有一个线程可以进入被 `synchronized` 保护的代码块或方法。 #### 2. `synchronized` 的三种应用方式 ` synchronized` 可以应用于以下三种场景: - **修饰实例方法**:当 `synchronized` 修饰实例方法时,的对象是当前实例(`this`)。这意味着只有持有该实例线程才能执行该方法[^1]。 - **修饰静态方法**:当 `synchronized` 修饰静态方法时,的对象是当前类的 `Class` 对象。所有线程在调用该静态方法时都需要获取类级别的[^3]。 - **修饰代码块**:通过指定一个明确的对象作为,`synchronized` 可以保护特定的代码块。例如: ```java synchronized (lock) { // 临界区代码 } ``` 这种方式提供了更细粒度的控制[^2]。 #### 3. 字节码指令实现 在JVM层面,`synchronized` 的实现依赖于两个字节码指令: - **`monitorenter`**:线程在进入 `synchronized` 块或方法时会执行此指令,尝试获取对象的- **`monitorexit`**:线程在退出 `synchronized` 块或方法时会执行此指令,释放对象的[^3]。 这两个指令的操作是原子的,确保了的获取和释放过程的安全性。 #### 4. 的状态升级 ` synchronized` 的状态会根据竞争情况动态升级,从偏向到轻量级再到重量级。以下是状态升级的过程: - **偏向**:当没有线程竞争时,JVM会假设只会被一个线程持有。此时,`Mark Word` 中存储的是偏向线程的ID,避免频繁的获取和释放操作[^5]。 - **轻量级**:当有线程竞争但竞争不激烈时,JVM会使用自旋的方式尝试获取。这种方式避免了线程切换的开销。 - **重量级**:当竞争非常激烈时,JVM会将线程挂起,进入操作系统级别的等待队列。 #### 5. 示例代码解析 以下是一个典型的 `synchronized` 使用示例: ```java public class SynchronizedExample { private int count = 0; public synchronized void increment() { count++; } public static void main(String[] args) throws InterruptedException { SynchronizedExample example = new SynchronizedExample(); Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { example.increment(); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { example.increment(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("Count: " + example.count); } } ``` 在此示例中,`increment` 方法被 `synchronized` 修饰,因此两个线程在调用该方法时会互斥执行[^1]。 #### 6. 注意事项 - `synchronized` 的对象必须明确且一致。如果对象不同,可能会导致线程之间的竞争无法正确解决[^1]。 - 在高并发场景下,`synchronized` 的性能可能不如其他机制(如 `ReentrantLock`),因为它缺乏一些高级特性(如公平、条件变量等)[^4]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值