资讯专栏INFORMATION COLUMN

@Java | Thread & synchronized - [ 线程同步锁 基本使用]

Michael_Lin / 1052人阅读

摘要:线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他非同步方法对于静态同步方法,锁是针对这个类的,锁对象是该类的对象。

对实现了Runnable或者Callable接口类,可以通过多线程执行同一实例的runcall方法,那么对于同一实例中的局部变量(非方法变量)就会有多个线程进行更改或读取,这就会导致数据不一致,synchronized(关键字)可以解决多线程共享数据同步的问题
synchronized使用说明 作用范围
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

修饰一个代码块:被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象

修饰一个非静态方法:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象

修改一个静态的方法:其作用的范围是整个静态方法,作用的对象是这个类的所有对象

修改一个类:其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象

高能提示:
No1 > synchronized修饰的非静态方法:如果一个对象多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,则这个线程所属对象其它线程不能同时访问这个对象任何一个synchronized方法
No2 > synchronized关键字是不能继承的:基类的方法synchronized function(){}在继承类中并不自动是synchronized function(){},而是变成了function(){}。继承类需要你显式的指定它的某个方法为synchronized方法,可以通过子类调用父类的同步方法来实现同步
No3 > 针对synchronized修饰代码块和非静态方法,本质上锁的是代码块或非静态方法对应的对象代码块是synchronized标注的变量,非静态方法是所在类对应的实例),如果是不同的对象是可以同时访问的
No4 > 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制
No5 > 每个对象只有一个锁(lock)与之相关联
No6 > 在定义接口方法时不能使用synchronized关键字
No7 > 构造方法不能使用synchronized关键字,但可以使用synchronized代码块来进行同步
1. 修饰一个代码块
public void syncCode(Object o) {
    synchronized (o) {// 同步代码块}
}
上面的锁就是o这个对象,当然多个线程同步需要保证o这个对象是同一个,这是有明确的对象作为锁的情况,如果只是想单纯的让某一段代码同步,并没有明确的对象作为锁,可以创建一个特殊的instance变量来充当锁
synchronized(o)修饰的代码块,其中o可以取值一个对象或者一个变量或者this亦或者Clz.class
public class Sync implements Runnable {
    private byte[] lock = new byte[0];
    public void syncCode() {
        synchronized (lock) {// 同步代码块}
    }
    public void run ....
}
零长度的byte数组对象创建起来将比任何对象都经济,查看编译后的字节码,生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码
2. 修饰一个非静态方法
public synchronized void method() {// .....}
此时锁的是调用这个同步方法的对象
3. 修饰一个静态方法
public synchronized static void method() {// .....}
synchronized修饰的静态方法锁定的是这个类的所有对象
4. 修饰类
public class Sync implements Runnable {
    public void syncCode() {
        synchronized (Sync.class) {// 同步代码块}
    }
    public void run ....
}
和作用于静态方法一样,synchronized作用于一个类时,是给这个类加锁,类的所有对象用的是同一把锁
总结

线程同步的目的是为了保护多个线程反问一个资源时对资源的破坏。

线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他非同步方法

对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。

对于同步,要时刻清醒在哪个对象上同步,这是关键。

编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,对"原子"操作做出分析,并保证原子操作期间别的线程无法访问竞争资源。

当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。

死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小,一旦程序发生死锁,程序将死掉

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69513.html

相关文章

  • @Java | Thread & synchronized - [ 多线程 基本使用]

    摘要:线程线程是进程中的一个实体,作为系统调度和分派的基本单位。下的线程看作轻量级进程。因此,使用的目的是让相同优先级的线程之间能适当的轮转执行。需要注意的是,是线程自己从内部抛出的,并不是方法抛出的。 本文及后续相关文章梳理一下关于多线程和同步锁的知识,平时只是应用层面的了解,由于最近面试总是问一些原理性的知识,虽说比较反感这种理论派,但是为了生计也必须掌握一番。(PS:并不是说掌握原理不...

    zhunjiee 评论0 收藏0
  • @Java | Thread & synchronized - [ 多线程 理论知识]

    摘要:死亡线程方法执行结束,或者因异常退出了方法,则该线程结束生命周期。死亡的线程不可再次复生。直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。枚举程序中的线程。强迫一个线程等待。通知一个线程继续运行。 一. 线程状态转换图 showImg(https://segmentfault.com/img/bV38ef?w=968&h=680); 线程间的状态转换说明: 新建(new)...

    harryhappy 评论0 收藏0
  • Java线程&高并发

    摘要:线程启动规则对象的方法先行发生于此线程的每一个动作。所以局部变量是不被多个线程所共享的,也就不会出现并发问题。通过获取到数据,放入当前线程处理完之后将当前线程中的信息移除。主线程必须在启动其他线程后立即调用方法。 一、线程安全性 定义:当多个线程访问某个类时,不管运行时环境采用何种调度方式,或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行...

    SQC 评论0 收藏0
  • JAVA线程机制解析-volatile&synchronized

    摘要:当一个线程持有重量级锁时,另外一个线程就会被直接踢到同步队列中等待。 java代码先编译成字节码,字节码最后编译成cpu指令,因此Java的多线程实现最终依赖于jvm和cpu的实现 synchronized和volatile 我们先来讨论一下volatile关键字的作用以及实现机制,每个线程看到的用volatile修饰的变量的值都是最新的,更深入的解释就涉及到Java的内存模型了,我们...

    dendoink 评论0 收藏0
  • Java并发编程之线程同步

    摘要:变量对所有的线程都是可见的,对变量所有的写操作都能立即反应到其他线程之中,即变量在各个线程中是一致的。因为该在释放等待线程后可以重用,所有称为循环的。 线程安全就是防止某个对象或者值在多个线程中被修改而导致的数据不一致问题,因此我们就需要通过同步机制保证在同一时刻只有一个线程能够访问到该对象或数据,修改数据完毕之后,再将最新数据同步到主存中,使得其他线程都能够得到这个最新数据。下面我们...

    lowett 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<