【学习笔记】线程原子性-锁 synchronized的用法(1)

简介: 【学习笔记】线程原子性-锁 synchronized的用法

线程安全性的定义:

当多个线程访问某个类的时候,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么我们就称则这个类是线程安全的

原子性的锁有两种:

synchronized:是Java中的关键字,是一种同步锁,依赖于JVM
Lock:依赖特殊的CPU指令,代码实现,ReentrantLock

这里我们先来了解synchronized

1、修饰代码块:大括号括起来的代码,作用于调用的对象

2、修饰方法:整个方法,作用于调用的对象

3、修饰静态方法:整个静态方法,作用于所有对象

4、修饰类:括号括起来的部分,作用于所有对象

修饰代码块

package com.lyy.concurrency.sync;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SynchronizedExample1 {
    // 修饰一个代码块
    public void test1(int j){
        synchronized (this){
            for (int i = 0; i < 10; i++) {
                System.out.println("test1   j:"+j+" — i:"+i);
            }
        }
    }
    public static void main(String[] args) {
        SynchronizedExample1 example1 = new SynchronizedExample1();
        SynchronizedExample1 example2 = new SynchronizedExample1();
        ExecutorService executorService = Executors.newCachedThreadPool();//声明一个线程池
        //加上线程池相当于我们调用了两个线程
        //两个线程调用了同一个对象
        executorService.execute(() ->{
            example1.test1(1);
        });
        executorService.execute(() ->{
            example2.test1(2);
        });
    }
}

返回结果:

test1   j:1 — i:0
test1   j:1 — i:1
test1   j:1 — i:2
test1   j:1 — i:3
test1   j:1 — i:4
test1   j:1 — i:5
test1   j:1 — i:6
test1   j:1 — i:7
test1   j:1 — i:8
test1   j:1 — i:9
test1   j:2 — i:0
test1   j:2 — i:1
test1   j:2 — i:2
test1   j:2 — i:3
test1   j:2 — i:4
test1   j:2 — i:5
test1   j:2 — i:6
test1   j:2 — i:7
test1   j:2 — i:8
test1   j:2 — i:9

线程1和线程2按照各自顺序执行,线程一和线程二都能够按照自己的同步代码走下去,但是不一定能保证线程一执行完之后才到线程二执行,这就要看哪一个线程能够率先抢到资源。

修饰方法

package com.lyy.concurrency.sync;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SynchronizedExample1 {
    //修饰一个方法 
    public synchronized void test2(int j){
        for (int i = 0; i < 10; i++) {
            System.out.println("test2 j:"+j+" — i:"+i);
        }
    }
    public static void main(String[] args) {
        SynchronizedExample1 example1 = new SynchronizedExample1();
        SynchronizedExample1 example2 = new SynchronizedExample1();
        ExecutorService executorService = Executors.newCachedThreadPool();//声明一个线程池
        //加上线程池相当于我们调用了两个线程 
        //两个线程调用了同一个对象
        executorService.execute(() ->{
            example1.test2(1);
        });
        executorService.execute(() ->{
            example2.test2(2);
        });
    }
}

返回结果:

test2 j:1 — i:0
test2 j:1 — i:1
test2 j:1 — i:2
test2 j:1 — i:3
test2 j:1 — i:4
test2 j:1 — i:5
test2 j:1 — i:6
test2 j:1 — i:7
test2 j:2 — i:0
test2 j:2 — i:1
test2 j:2 — i:2
test2 j:2 — i:3
test2 j:2 — i:4
test2 j:2 — i:5
test2 j:2 — i:6
test2 j:2 — i:7
test2 j:2 — i:8
test2 j:1 — i:8
test2 j:2 — i:9
test2 j:1 — i:9

我们可以看到1 和2 是交替运行的,但是各自都是按照顺序在执行,这里是因为修饰代码块只能作用于当前调用的对象,我们这里是调用了两个方法所以,两个线程则互不干扰,都是各自执行各自的代码,同步是整个方法


注意:如果SynchronizedExample1 是个子类 那么实现test2的时候是不会携带synchronized关键字 ,因为synchronized是不属于方法声明的一部分,因此,synchronized关键字不能被继承,如果想要去实现这个子类继承synchronized,需要我们手动是实现这个功能


目录
相关文章
|
1月前
|
编解码 数据安全/隐私保护 计算机视觉
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
如何使用OpenCV进行同步和异步操作来打开海康摄像头,并提供了相关的代码示例。
80 1
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
|
14天前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
41 4
|
1月前
|
Java 开发者
在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选
【10月更文挑战第6天】在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选。相比 `synchronized`,Lock 提供了更灵活强大的线程同步机制,包括可中断等待、超时等待、重入锁及读写锁等高级特性,极大提升了多线程应用的性能和可靠性。通过示例对比,可以看出 Lock 接口通过 `lock()` 和 `unlock()` 明确管理锁的获取和释放,避免死锁风险,并支持公平锁选择和条件变量,使其在高并发场景下更具优势。掌握 Lock 接口将助力开发者构建更高效、可靠的多线程应用。
24 2
|
1月前
|
Java 应用服务中间件 测试技术
Java21虚拟线程:我的锁去哪儿了?
【10月更文挑战第8天】
32 0
|
1月前
FFmpeg学习笔记(二):多线程rtsp推流和ffplay拉流操作,并储存为多路avi格式的视频
这篇博客主要介绍了如何使用FFmpeg进行多线程RTSP推流和ffplay拉流操作,以及如何将视频流保存为多路AVI格式的视频文件。
170 0
|
1月前
|
安全 调度 数据安全/隐私保护
iOS线程锁
iOS线程锁
26 0
|
1月前
|
Java 编译器 程序员
【多线程】synchronized原理
【多线程】synchronized原理
59 0
|
1月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
43 1
C++ 多线程之初识多线程
|
24天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3
|
24天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
16 2