首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >线程:对同步的深入理解

线程:对同步的深入理解
EN

Stack Overflow用户
提问于 2013-12-18 13:25:17
回答 1查看 194关注 0票数 1

我只想在同步的同时对内在机制有一个更深入的了解。我准备了3个例子。我有一些问题涉及到每个问题。下面是第一个例子:

代码语言:javascript
运行
AI代码解释
复制
public class SyncExamples 
{

    SyncClass sync1, sync2;


    public void execute1()
    {
        sync1 = new SyncClass();
        sync1.process();
    }


    public void execute2()
    {
        sync2 = new SyncClass();
        sync2.process();
    }



    class SyncClass
    {

        public synchronized void process()
        {

        }
    }
}

SyncClass的方法进程()是同步的。但是由于在类SyncExamples 中创建了两个不同的对象( of SyncClass ),它们都可以同时执行,不是吗?它们引用不同的对象,因此没有任何同步。是对的吗?

第二个例子:

代码语言:javascript
运行
AI代码解释
复制
public class SyncExamples 
{

    SyncClass sync1 = new SyncClass();


    public void execute1()
    {       
        sync1.process();
    }


    public void execute2()
    {       
        sync1.process();
    }




    class SyncClass
    {

        public synchronized void process()
        {

        }
    }
}

所以在这个例子中,它们引用的对象是相同的。所以这里有一个互斥物。它们是同步的。但让我们来看看我最感兴趣的例子。

代码语言:javascript
运行
AI代码解释
复制
public class SyncExamples 
{

    SyncClass sync1 = new SyncClass();
    ReadWriteLock lock = new ReentrantReadWriteLock(); 


    public void execute1()
    {       
        lock.writeLock().lock();
        sync1.process();
        lock.writeLock().unlock();
    }


    public void execute2()
    {       
        execute1();
    }


    public void execute3()
    {       
        sync1.process();
    }


    public void execute4()
    {       
        execute1();
    }


    class SyncClass
    {

        public void process()
        {

        }
    }
}

execute2()启动execute1()。execute1()锁定sync1.process()。因此,execute4()必须等待,直到sync1.process()被execute1()解锁。但是execute3()呢?它不引用execute1(),而是直接调用sync1.process()而不使用任何锁。因此,execute1()设置的锁对execute3()无效吗?是那么回事吗?该锁仅对引用execute1()的调用有效,因为此方法定义了锁?

一天后我添加了以下示例:

代码语言:javascript
运行
AI代码解释
复制
public class SyncExamples 
{

    List list = new ArrayList(); 


    public void processList1()
    {       
        synchronized(list)
        {
        }
    }


    public void processList2()
    {       
        synchronized(list)
        {
        }
    }


    public void execute3()
    {       
        processList1();
    }


    public void execute4()
    {       
        processList2();
    }
}

我想澄清最后一个例子。现在我有了一个想要同步的列表。方法processList1()同步列表.方法processList2()也会这样做。但它们能同时执行吗?同步是全局锁定列表(我指的是所有来自其他方法的其他访问),还是仅与特定方法结合使用?在本例中,我仍然不明白execute3()和execute4()是否可以同时执行,因为它们引用了不同的方法。同步阻止对其块的第二次访问。但是有几种方法想要访问列表,它们使用自己的同步块。因此,如果processList1()锁定了列表,那么这个列表是否锁定为processList2()?或者这个锁对processList2()无效,因为它是一个不同的方法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-12-18 13:33:07

第一个问题:正确

第二种情况:是的,表现得像互斥。

第三个问题:正确

回答编辑

synchronized块使用它的参数对象作为块的锁(或者更好的是互斥对象)。因此,如果两个线程到达同一对象上的关键部分synchronized,则只允许一个线程进入其关键部分,而另一个线程则等待此线程退出关键部分。

synchronized方法只是synchronized块的语法糖,因此

代码语言:javascript
运行
AI代码解释
复制
class SyncClass
{
    public synchronized void process()
    {

    }
}

可以写成

代码语言:javascript
运行
AI代码解释
复制
class SyncClass
{
    public void process()
    {
        synchronized(this)
        {
            // whole body of process() inside this block
        }
    }
}

所以,回答你的问题

  • synchronized将全局锁定list (或任何其他用作其参数的对象),而不只是针对特定的方法。您可以在代码中的任何地方对对象进行同步,并且无论包含的方法/类或调用层次结构如何,同步部分都将以互斥方式运行。
  • processList1()processList2()不会并发执行。一次只能执行一个。(这假设您在synchonized块之外没有代码。)
  • execute3()和execute4()可以并发执行,但只能执行到到达synchronized部分的程度。也就是说,对processList1()processList2()的调用以及这些调用之前的任何代码-- execute3/4()方法可以并发执行,但是synchronized部分中的代码不能并发执行。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20668721

复制
相关文章
深入理解线程通信
两个线程通过对同一对象调用等待 wait() 和通知 notify() 方法来进行通讯。
爱明依
2022/04/01
2500
深入理解线程通信
两个线程通过对同一对象调用等待 wait() 和通知 notify() 方法来进行通讯。
crossoverJie
2022/08/19
2450
深入理解线程通信
深入理解多线程
多线程是java中比较重要的一部分内容,使用多线程有许多的优点: - 提高应用程序的响应。对图形化界面更有意义,可增强用户体验。 - 程序需要实现一些需要等待的任务时,可以提高计算机系统CPU的利用率 - 改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改
栋先生
2018/09/29
7190
深入理解多线程
深入理解Java多线程(multiThread)多线程的基本概念线程同步wait,notify,notifyAll线程的生命周期
一个java程序启动后,默认只有一个主线程(Main Thread)。如果我们要使用主线程同时执行某一件事,那么该怎么操作呢? 例如,在一个窗口中,同时画两排圆,一排在10像素的高度,一排在50像素的高度。 如果只能在一个主线程里写出同时执行的程序,那就只能先在高度10画个圆,再快速在高度50画一个圆,平移后再在高度10画一个圆,....依此循环下去:
desperate633
2018/08/22
4580
深入理解Java多线程(multiThread)多线程的基本概念线程同步wait,notify,notifyAll线程的生命周期
对矩阵乘法的深入理解
本文是对《机器学习数学基础》第2章2.1.5节矩阵乘法内容的补充和扩展。通过本节内容,在原书简要介绍矩阵乘法的基础上,能够更全面、深入理解矩阵乘法的含义。
老齐
2021/03/11
1.6K0
对矩阵乘法的深入理解
深入理解JVM(③)线程与Java的线程
我们都知道,线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源调度(内存地址、文件I/O等),又可以独立调度。
纪莫
2020/07/14
6250
深入理解JVM(③)线程与Java的线程
进程和线程的深入理解
单CPU:一台单核处理器计算机 = 一个车间; 多CPU:一台多核处理器计算机 = 一座工厂;
全栈程序员站长
2022/09/17
1900
Java线程池深入理解
之前面试baba系时遇到一个相对简单的多线程编程题,即"3个线程循环输出ADC",自己答的并不是很好,深感内疚,决定更加仔细的学习《并发编程的艺术》一书,到达掌握的强度。(之前两月休息时间都花在了lo
用户1216676
2018/01/24
1.8K0
深入理解Java线程状态
实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态
JavaEdge
2019/09/16
5580
深入理解Java线程池
ThreadPoolExecutor采取上述步骤的总体设计思路,是为了在执行execute()方法时,尽可能地避免获取全局锁(那将会是一个严重的可伸缩瓶颈)。在ThreadPoolExecutor完成预热之后(当前运行的线程数大于等于corePoolSize),几乎所有的execute()方法调用都是执行步骤2,而步骤2不需要获取全局锁。
luoxn28
2020/11/12
6590
深入理解 Java 线程池
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。
静默虚空
2019/12/26
4940
深入理解 Java 线程池
作为测试,如何理解线程同步异步
② 主线程在执行任务1时,需等待任务1响应完成后,才能开始任务2,如任务1阻塞,则整个进程不能进行,这样的同步线程对执行效率有很大的影响(如下图)。
用户5521279
2021/01/25
1K0
深入理解JVM(③)再谈线程安全
我们在编写程序的时候,一般是有个顺序的,就是先实现再优化,并不是所有的牛P程序都是一次就写出来的,肯定都是不断的优化完善来持续实现的。因此我们在考虑实现高并发程序的时候,要先保证并发的正确性,然后在此基础上来实现高效。所以线程安全是高并发程序首先需要保证的。
纪莫
2020/07/16
4040
深入理解JVM(③)再谈线程安全
深入理解线程池底层原理
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
xcbeyond
2020/03/25
4130
深入理解线程池底层原理
深入理解Java之线程池
转载自:http://www.importnew.com/19011.html#comment-653957
天涯泪小武
2019/07/01
3620
深入理解JVM(线程部分) Note
由于计算机的存储设备与处理器的运算速度有几个数量级的差距,所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(Cache)来作为内存与处理器之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后再从缓存同步回内存之中,这样处理器就无须等待缓慢的内存读写了。
六月的雨
2020/03/27
4010
深入理解 Java 线程池的实现原理
如上述代码所示,其来自于java.lang.Thread类,State为Thread类的内部公共枚举类,表示线程的 6 种状态。
CG国斌
2021/12/07
2800
深入理解 Java 线程池的实现原理
线程的同步
比如买票,有窗口和柜台,窗口卖票和售票机卖票都会减少票的数量,一共100张票,通过窗口这个方法卖了70张票,售票机
用户2965768
2019/03/20
4270
线程的同步
对find xargs grep和管道的深入理解
这两个词我们在Linux命令中是很常见的。但是参数和标准输入其实是有区别的。我们日常使用的很多命令,例如ls -lah .中。l, a, h ,.都是命令ls的参数。至于标准输入,可以说它某种流数据。而通常来讲标准输入的流数据来源就是我们的终端输入。在Linux命令中,有些命令可以接收标准输入,有些是不能的。像上面的ls,就是只能接收参数,不能接收标准输入。像cat命令或echo命令,这些是可以的。
BUG弄潮儿
2022/06/30
6320
点击加载更多

相似问题

对Monad的深入理解

13

理解线程同步

10

HikariCP对Spring引导的深入理解

14

对javascript闭包的深入理解

51

对系列化的深入理解

13
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文