共享受限资源

理解并实现锁机制:保护共享资源的并发访问 通过使用锁机制,我们可以保护共享资源的并发访问,避免数据竞争和不一致性的问题。在编程中,锁是一种重要的工具,可以确保在任何给定时间点只有一个线程可以访问临界区代码。通过使用锁,我们确保了在任何给定时刻只有一个线程可以访问临界区代码,从而保护了共享资源的一致性。在上述示例中,我们递增了1000000次共享资源的值,并通过锁的机制保证了正确的结果。在编程中,锁是一种重要的机制,用于保护共享资源的并发访问。在下面的示例中,我们将使用Python编写一个简单的多线程程序,演示如何使用锁来保护共享资源。 阅读详情

一、解决共享资源竞争
1、原因:
我们永远不知道一个线程何时在运行。比如你坐在桌子边,正要去叉盘子中的最后一片实物,都够着它时,突然这片食物消失了,因为你的线程被挂起,另一个用餐者坐下并吃掉了它。

2、解决方式:
当一个资源被一个任务使用时,在其上加锁。第一个访问某项资源的任务必须锁定这项资源,是其他任务在被 解锁之前无法访问它,其被解锁之时,另一个任务就可以锁定这项资源并使用它。

方案:
基本上所有并发模式在解决线程冲突问题时,都是采用序列化访问共享资源的方案。这意味着在给定的时刻只允许一个任务访问共享资源。通常通过在代码前面加上一条锁语句来实现,锁语句产生了一种互相排斥的效果,所以这种机制常常被称为互斥量(mutex)。

3、互斥同步:
关键字:synchronized 和使用显式的Lock对象

3.1 synchronized

java以提供关键字synchronized的形式,为防止资源冲突提供内置的支持。当任务要执行被synchronized 关键字保护的代码片段时,它将检查锁是否可用,然后获得锁,执行代码,释放锁。

使用方法:

共享资源一般以对象的形式存在内存片段,但也可以是文件、输入/输出端口、或者打印机。要控制对共享资源的访问,需要把它包装进对象,然后所有要访问资源的方法都标记为synchronized 。

声明synchronized 方法的方式:

synchronized void f(){}

synchronized void g(){}

所有对象都含有单一的锁(也称为监视器)。当在对象上调用任意synchronized方法时,此对象都被加锁,这时该对象上的其他synchronized 方法只有等到前一个方法调用完毕 并释放锁之后才能被调用。所以对于特定对象来说,其所有synchronized 方法共享同一个锁,这可以被用来防止多个任务同时访问被编码为对象内存

注意在使用并发时将域设置为private是非常重要的,否则,synchronized 关键字就不能防止其他任务直接访问域,这样就会产生冲突。

锁具有重如机制:一个对象可以多次获得对象的锁。如果一个方法在同一个对象上调用了第二个方法,后者有调用了另一个方法,就会出现多次获得锁的情况。

针对每个类也有一个锁,所以synchronized static 方法可以在类的范围内防止对static数据的并发访问。

如果在你的类中有一个方法正在处理临界数据,那么你必须同步所有相关的方法,否则他就不能正常工作。

Brian的同步规则:

如果你在写一个变量,它可能接下来将被另一个线程读取,或者正在读取一个上一次已经被另一个线程写过的变量,那么你必须使用同步,并且读写线程都必须用相同的监视器锁同步。

3.2显式的Lock对象

在java SE5的java.util.concurrent类库中包含定义在java.util.concurrent.locks中的显式互斥机制。Lock对象必须被显式的创建、锁定和释放。

Lock lock = new ReentrantLock();
    public int locktest(){
       lock.lock();
        try{
            dosomething();
            return value;
        }finally {
            lock.unlock();
        }
    }

对lock()的调用你必须放在finally子句中带有unlock()的try-finally语句中,注意,return语句必须在try子句中出现,以确保unlock()不会过早发生,从而将任务暴露给第二个任务。

synchronized 和lock的使用场景:
一般使用synchronized,如果使用synchronized关键字时,某些事物失败了,那么就会抛出一个异常,但是你没有机会做任何清理工作,以维护系统使其处于良好状态。有了显式的Lock对象,你就可以使用finally子句将系统维护在正确的状态。

相比synchronized,ReentrantLock增加了一些高级功能

  • 尝试获取锁且最终会失败,或者尝试获取锁一段时间,然后放弃它.可以通过
tryLock() tryLock(long timeout, TimeUnit unit)
```实现。
- 等待可中断指当持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待,改为处理其他事情,可中断性对于处理执行时间非常长的同步块很有帮助。可以通过

lockInterruptibly()


- 公平锁指多个线程在等待同一个锁时,必须按照申请锁的时间顺序依次获得锁。可通过

ReentrantLock(true)

- 绑定多个条件指ReentrantLock对象可以同时绑定多个Condition对象,而synchroinzed中,锁对象的wait()和notify()或notifyAll()方法可以实现一个隐含的条件,如果要和多于一个条件关联的时,就需要额外的田间一个锁,ReentrantLock只需多次调用newCondition()方法即可。

ReentrantLock trylock的使用Demo:

public class AttemptLocking {
private ReentrantLock lock = new ReentrantLock();
public void untimed(){
boolean captured = lock.tryLock();
try{
System.out.println("tryLock() " + captured);
}finally {
if(captured){
lock.unlock();
}
}
}
public void timed(){
boolean captured = false;
try {
captured = lock.tryLock(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}

    try {
        System.out.println("tryLock(2, TimeUnit.SECONDS): " + captured);
    }finally {
        if(captured){
            lock.unlock();
        }
    }
}

public static void main(String[] args){
    final AttemptLocking al = new AttemptLocking();
    al.untimed();
    al.timed();
    new Thread(){
        {
            setDaemon(true);
        }
        public void run(){
            al.lock.lock();
            System.out.println("acquired ");
        }
    }.start();
    try {
        TimeUnit.MILLISECONDS.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Thread.yield();
    al.untimed();
    al.timed();
}

}


4、原子性、可见性和有序性

原子性:

原子操作是不能被线程调度机制中断的操作;一旦操作开始,那么它一定可以在可能发生 "上下文切换"之前(切换到其他线程执行)执行完毕。

原子性可以应用与除long和double之外的所有基本类型的读写操作。对于除long和double之外的基本类型变量的操作,可以保证他们被当作不可分(原子)的操作来操作内存。当定义long或double变量时,如果使用volatile关键字就会获得原子性。

可见性:

可见性指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。java内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量的值这种依赖主内存作为传递媒介的方式实现可见性的。在非volatile变量的原子操作不必刷新到主内存中去,因此其他读取该域的任务不必看到这个新值。synchronized和final也实现了可见性

有序性:

java程序有序性总结为一句话:如果在本线程内观察,所有的操作都是有序的;如果在一个线程中观察另一个线程所有的操作都是无序的。前半句指“线程内表现为串行的语义”,后半句指“指令重排序”现象和“工作内存和主内存同步延迟”现象。
volatile关键字和synchronized关键字保证了线程之间操作的有序性。volatile关键字本身包含禁止指令重排序,synchronized则由“一个变量在同一时刻只允许一个线程对其进行lock操作”这条规则获得的,持有同一个锁的两个同步块只能串行地进入。

5、线程本地存储

防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享。

创建和管理本地线程由java.lang.ThreadLocal类来实现。线程本地存储是一种自动化机制,可以为使用相同变量的每个不同的线程都创建不同的存储。


public class ThreadLocalVariableHolder {

private static ThreadLocal<Integer> value = new ThreadLocal<Integer>(){
    @Override
    protected Integer initialValue() {
        Random random = new Random(47);
        return random.nextInt(1000);
    }
};

public static void increment(){
    value.set(value.get() + 1);

}

public static int get(){
    return value.get();
}

public static void main(String[] args) throws InterruptedException {
    ExecutorService exec = Executors.newCachedThreadPool();
    for (int i = 0; i < 5; i++){
        exec.execute(new Accessor(i));
    }
    TimeUnit.SECONDS.sleep(3);
    exec.shutdownNow();

}

static class Accessor implements Runnable{

    private final int id;

    public Accessor(int idn){
        id = idn;
    }
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()){
            ThreadLocalVariableHolder.increment();
            System.out.println(this);
            Thread.yield();
        }
    }

    @Override
    public String toString() {
        return "# " + id + ": " + ThreadLocalVariableHolder.get();
    }
}

}


开源数显表 开源数显表,广泛应用于车床、铣床、磨床、镗床、火花机、线切割等。市面上此类液晶数显表多数都是基于此项目。 一、基本配置 硬件 主控:STM32F407VGT6 LCD:群创AT070TN92 显示驱动:RA8875 光栅尺:3 x 输入(X/Y/Z) 串口:1 x MAX3232 继电器:2 x 输出 存储:AT24C64 模拟输入:LM324C 电源:AC 220V 软件 工程版本:Keil 5 STM32库:V1.4.0 图形界面:uCGUI 多语言支持:中文、英文 二、项目文 阅读详情

相关推荐

PID循迹控制算法

前言  让小车进行循迹最重要的是获取车相对于循迹线的位置,关于循迹模块的原理我已经在之前的一篇博客上讲过,如果大家没看过的话可以点此链接:PID循迹模块原理。 PID循迹原理简介 图1 循迹车寻线行走图示 图2 市场常见循迹传感器  PID循迹的原理我们大致可以用常识性思维去思考下,如图1所示为循迹车寻线行走图示,现在小车要按照中间那条黑线循迹行走,如果车头往左偏则需要控制方向盘让车往右转,车头往又偏则需要让车往左转。但是仅仅只有左转和右转的话,车一到左边就向右转,一到右边就向左转,则车会来回在线左右晃动

Dinvent的博客 7万+

Win10系统,使用钉钉会议共享屏幕的时候,别人看到的都是全黑或全白屏幕

Win10系统钉钉7.6.0。

本博客,博文仅代表个人操作经验,不能完全解决你的问题,仅供参考,佛系回复。 3623

用LTspice仿真Buck电路输出电容:从参数计算到波形优化的全流程演示

本文详细介绍了使用LTspice仿真Buck电路输出电容的全流程,从理论计算到波形优化。通过解析关键参数如纹波电压、瞬态响应和ESR,结合工程计算方法和LTspice仿真技巧,帮助工程师优化Buck电路设计,解决输出纹波过大和瞬态响应不佳的问题。

night的博客 851

并发(3)共享受限资源

共享受限资源

SJZYLC的专栏 377

利用HTML+CSS设计PPT:html-to-pptx实现自动化转换与可编辑输出

在办公自动化和前端开发领域,将网页技术应用于文档生成是一个重要的技术方向。其核心原理在于通过解析HTML/CSS的结构与样式,将其映射为目标文档的原生对象模型。这项技术的价值在于,它能够将Web技术栈强大的布局与样式能力(如Flexbox、CSS Grid)与办公软件(如Microsoft PowerPoint)的广泛兼容性和可编辑性相结合。在实际应用场景中,这种技术特别适合需要快速生成兼具设计感与实用性的演示文稿,例如数据报告、产品发布和营销材料。本文探讨的html-to-pptx项目正是这一思路的工程实

weixin_30652491的博客 486

【推荐100个unity插件】unity实现交互式火焰 —— Ignis

Ignis是一款Unity互动式消防系统插件,可轻松将物体转换为可燃物。支持固体、植被、蒙皮网格和地形树木等多种对象类型,提供火焰蔓延、熄灭等效果。安装需通过Unity Package Manager添加Visual Effects Graph,并按照指引转换目标物体材质。使用盒型碰撞体或网格计算燃烧区域,可自定义火焰参数和视觉效果。内置多种转换选项,如Flammable Vegetation、Flammable Skinned Mesh等,适用于不同场景需求。注意使用前需备份材质和地形数据,并提供性能优化

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 2235

【Java用法】共享受限资源,解决共享资源竞争,Brian的同步规则

本文目录 一、共享受限资源 二、解决共享资源竞争 2.1 使用synchronized关键字 2.2 显示的使用Lock锁 三、Brian的同步规则 一、共享受限资源 可以把单线程程序当作在问题域求解的单一实体,每次只能做一件事情。因为只有一个实体,所以永远不用担心诸如“两个实体试图同时使用同一个资源”这样的问题。比如,两个人在同一个地方停车,两个人同时走过一扇门,甚至是两个人同时说话。 有了并发就可以同时做多件事情了,但是,两个或多个线程彼此互相干涉的问题也就出现了。如果不防范这种冲突,就

No8g攻城狮的博客 765

把 LangGraph 当“工作流引擎”用:与传统 BPM 的差异与融合策略

首先,我们来回顾一下有限状态机(FSM)的基本定义——一个 FSM 可以用一个五元组MQΣδq0FMQΣδq0​FQQQ有限状态集合,包含 FSM 所有可能的状态;Σ\SigmaΣ有限输入字母表,包含 FSM 所有可能的输入;δ\deltaδ状态转移函数,定义了 FSM 从当前状态q∈Qq \in Qq∈Q接收输入σ∈Σσ∈Σ后,转移到的下一个状态q′∈Qq' \in Qq′∈Q,即δQ×Σ→QδQ×Σ→Q。

AI 原生应用开发的博客 227

钉钉直播 — 为什么直播屏幕共享显示黑屏?(仅针对mac端)

发现mac钉钉共享屏幕时,可选择的全是黑的,对方无法看到 参考:https://www.dingtalk.com/qidian/help-detail-1060821672.html 您好,您可以通过以下两种方式操作: 第一种:打开“系统偏好设置”》“安全性与隐私” 2.找到“麦克风/摄像头” 》钉钉前面打钩; ...

GXQ的博客 1万+

YOLOv11改进 | 模型知识蒸馏篇 | 利用模型蒸馏改进YOLOv11进行无损涨点 | CWDLoss(在线蒸馏 + 离线蒸馏)

这篇文章给大家带来最新改进的是模型的蒸馏利用教师模型指导学生模型从而进行模型的涨点,本文的内容不仅可以用于论文中,在目前的绝大多数的工作中模型蒸馏是一项非常重要的技术,所以大家可以仔细学习一下本文的内容,本文从YOLOv11的项目文件为例,进行详细的修改教程,文章内包括完整的修改教程,针对小白我出了视频修改教程,如果你还不会我提供了修改后的文件大家直接运行即可,所以说不用担心不会适用!模型蒸馏真正的无损涨点,蒸馏你只看这一篇文章就足够了!欢迎大家订阅我的专栏一起学习YOLO!

Snu77的博客 3296

手把手教你学Simulink--基于飞行控制与稳定性的场景实例:多旋翼无人机在风扰动下的稳定性分析

本文介绍了使用Simulink仿真多旋翼无人机在风扰动下稳定性的方法。通过构建包含飞行器动力学模型、PID控制系统和环境模拟模块的仿真系统,分析了无人机在不同风速条件下的飞行性能。详细说明了从创建模型、设置动力学方程、设计PID控制器到添加风扰动模型的完整流程,并提供了性能评估指标。该方法可用于验证控制系统有效性,优化飞行稳定性参数,为无人机控制系统的设计和调试提供参考。

MHD0815的博客 327

Java并发之共享受限资源

当使用多线程时,多个线程之间彼此相互干涉的问题也就出现了。比如多线程爬虫时,多个线程同时维护一个uri队列,这样就可能会存在冲突。例如线程A准备取uri_a,但是线程B突然就抢走了uri_a,再比如线程A正在读取uri_b,此时线程B也来读取uri_b了。 boolean 是原子的,线程安全的。 java中递增操作自身也需要多个步骤,所以不是原子操作,在递增过程中也可能被线程机制挂起。1. 解决共

惜暮 1660

rk3568 修改开机动画

bootanimation.zip是一个Android设备启动时播放的动画文件,它包含了一系列的图片和描述文件,用于描述动画的播放顺序和持续时间。

weixin_35723192的博客 2727

Java编程思想 之 共享受限资源

并发程序可以同时做多件事情,但是, 两个或多个线程彼此互相干涉的问题也就出现了。以下例子出自<< java编程思想第4版>>一书的并发部分.

585

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java多线程共享受限资源

一、多线程并发问题 所谓的多线程并发问题,就是在多线程的情况下,一个任务对共享数据操作的中间状态暴露给其他任务。即在一个线程的任务中,会对一个多线程共享的数据进行操作,在操作完成之前,对数据的更改对其他线程可见,此时,如果线程挂起,并驱动其他线程任务,则其他线程任务会访问到这个数据的中间状态,即访问到错误的数据。 多线程问题的基础是在多线程下使用同一个对象操作这个对象的同一个成员属性。 二、

fso918的专栏 1805

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java 线程——共享受限资源

谈起线程,有很重要的一点是关于解决线程间数据同步,或者说资源的访问问题。 参考java编程思想 书籍,在21章第三节开始讲有关共享资源问题,所以接下来探讨关于线程同步机制;解决线程并发引起的数据访问问题,实际上就要控制访问的顺序和确定相关的规则,一般的我们可以用以下方式去实现: synchronized 关键字实现可以参考文章 synchronized 又分为同步方法和同步代码块 同步方...

sjh_389510506的博客 487

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

资源受限视觉智能体共享状态协作故障诊断与根因分析

在多智能体系统与机器人领域,协作的核心在于智能体间对环境和任务状态达成共识,这通常通过共享状态机制实现。其基本原理是智能体通过感知、通信与信息融合,构建并维护一个共同的任务视图,从而协调行动。该技术的价值在于能显著提升群体完成复杂任务的效率与鲁棒性。其应用场景广泛,涵盖协同搬运、环境勘探、无人机编队等。然而,在计算、通信、感知资源受限的严苛现实条件下,共享状态协作极易失效,表现为智能体行为冲突、任务停滞等故障模式。本文聚焦于资源受限视觉智能体这一典型场景,系统阐述如何通过多层次日志、差异分析与可视化工具链,

weixin_30911451的博客 458

Java并发(三):共享受限资源

Java并发(三):共享受限资源 一、Java并发共享受限资源的问题 在使用Java并发时,如果两个或者多个线程需要访问共享资源,那么就会出现共享资源竞争的问题,多个线程试图同时访问同一个共享资源。 当线程A与线程B都是对共享资源进行写入数据,那么由于线程调度机制的不确定性,在线程A写入一半数据时可能出现线程B调度,并写入数据,这将导致数据错误。 二、解决共享资源竞争 使用线程时的一个基本问题是...

weixin_38196407的博客 541

并发---共享受限资源

可以把单线程程序当做在问题域求解的单一实体,每次只能做一件事情。因为只有一个实体,所以永远不用担心诸如“两个实体试图同时使用同一个资源”。 并发就可以同时做多件事情了,但是,两个或多个线程彼此互相干涉的问题也就出现了。 不正确地访问资源 import java.util.concurrent.ExecutorService; import java.util.concurrent.E...

进阶的小程媛儿 458

(二)共享受限资源

本章主要讲如何解决访问共享资源时的竞争问题。 其中关于synchronized关键子,显式lock锁等详细内容看我写的这篇文章。 下面主要讲原子类、临界区和线程本地存储: 原子类 J2SE 5.0提供了一组atomic class来帮助我们简化同步处理。基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增、减、赋值(更新)操作. 比如对于

wuchao0508的博客 306

初阶并发编辑之——共享受限资源

不正确的访问资源   我们先看一个例子:class addOne implements Runnable{ private static int value=0; @Override public void run() { //System.out.println(Thread.currentThread()); try { T

qq_33667439的博客 331

21.3 共享受限的资源

21.3.1 不正确的访问 当有两个或更多的任务竞争响应某个条件,产生冲突或不一致结果 21.3.2 解决共享资源竞争 java提供了关键字synchronize来保护代码片段,当任务要执行被synchronize关键字保护的代码片段的时候,它将检查锁是否可用,然后获取锁,执行代码,释放锁。 当在对象上调用器任意synchronize方法时候,此对象都被加锁,这时对象上的其他syn

CodeMyDream的专栏 385

并发(5):共享受限资源(上)

可以把单线程程序当作问题域求解的单一实体,每次只能做一件事情。因为只有一个实体,所以永远不用担心诸如“两个实体试图同时使用同一个资源”这样的问题——比如,两个人在同一个地方停车,两个人同时走过一扇门,甚至两个人同时说话。有了并发就可以同时做多件事情了,但是,两个或多个线程彼此互相干涉的问题也就出现了。如果不防范这种冲突,就可能发生两个线程同时试图访问同一个银行账户,或向同一个打印机打印,改变同一个值等诸如此类的问题。

游王子og的博客 404

共享受限资源,Brian的同步规则

说明:如果一个变量是boolean,则此变量是原子性的,即赋值和返回值简单的操作在发生时没有中断的可能。        递增不是原子性炒作。 解决共享资源竞争:      1. 通过加锁,锁语句会产生相互排斥的效果,此种机制也成为互斥量。          通过关键之synchronized 关键字锁也称为监视器。      2. 通过使用显式的Lock对象,通过调用lock()与unl...

weixin_33897722的博客 216
上一篇: 基本的线程机制
下一篇: Web与JS交互
coderPlus
博客等级 码龄12年 1粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值