【学习笔记】线程原子性-锁 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,需要我们手动是实现这个功能


目录
相关文章
|
9天前
|
Java 开发者 C++
Java多线程同步大揭秘:synchronized与Lock的终极对决!
Java多线程同步大揭秘:synchronized与Lock的终极对决!
42 5
|
11天前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
Java并发编程实战:使用synchronized关键字实现线程安全
26 0
|
11天前
|
数据采集 存储 安全
如何确保Python Queue的线程和进程安全性:使用锁的技巧
本文探讨了在Python爬虫技术中使用锁来保障Queue(队列)的线程和进程安全性。通过分析`queue.Queue`及`multiprocessing.Queue`的基本线程与进程安全特性,文章指出在特定场景下使用锁的重要性。文中还提供了一个综合示例,该示例利用亿牛云爬虫代理服务、多线程技术和锁机制,实现了高效且安全的网页数据采集流程。示例涵盖了代理IP、User-Agent和Cookie的设置,以及如何使用BeautifulSoup解析HTML内容并将其保存为文档。通过这种方式,不仅提高了数据采集效率,还有效避免了并发环境下的数据竞争问题。
如何确保Python Queue的线程和进程安全性:使用锁的技巧
|
9天前
|
安全 Java 开发者
Java多线程同步:synchronized与Lock的“爱恨情仇”!
Java多线程同步:synchronized与Lock的“爱恨情仇”!
70 5
|
9天前
|
Java 开发者
在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选
在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选。相比 `synchronized`,Lock 提供了更灵活强大的线程同步机制,包括可中断等待、超时等待、重入锁及读写锁等高级特性,极大提升了多线程应用的性能和可靠性。通过示例对比,可以看出 Lock 接口通过 `lock()` 和 `unlock()` 明确管理锁的获取和释放,避免死锁风险,并支持公平锁选择和条件变量,使其在高并发场景下更具优势。掌握 Lock 接口将助力开发者构建更高效、可靠的多线程应用。
11 2
|
9天前
|
Java 测试技术
Java多线程同步实战:从synchronized到Lock的进化之路!
Java多线程同步实战:从synchronized到Lock的进化之路!
71 1
|
11天前
|
Java 开发者
Java多线程教程:使用ReentrantLock实现高级锁功能
Java多线程教程:使用ReentrantLock实现高级锁功能
17 1
|
4天前
|
安全 Java API
Java线程池原理与锁机制分析
综上所述,Java线程池和锁机制是并发编程中极其重要的两个部分。线程池主要用于管理线程的生命周期和执行并发任务,而锁机制则用于保障线程安全和防止数据的并发错误。它们深入地结合在一起,成为Java高效并发编程实践中的关键要素。
4 0
|
10天前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
|
13天前
|
Java 开发者
解锁Java并发编程的秘密武器!揭秘AQS,让你的代码从此告别‘锁’事烦恼,多线程同步不再是梦!
【8月更文挑战第25天】AbstractQueuedSynchronizer(AQS)是Java并发包中的核心组件,作为多种同步工具类(如ReentrantLock和CountDownLatch等)的基础。AQS通过维护一个表示同步状态的`state`变量和一个FIFO线程等待队列,提供了一种高效灵活的同步机制。它支持独占式和共享式两种资源访问模式。内部使用CLH锁队列管理等待线程,当线程尝试获取已持有的锁时,会被放入队列并阻塞,直至锁被释放。AQS的巧妙设计极大地丰富了Java并发编程的能力。
25 0