三、synchronized关键字

news/2024/5/20 13:54:11 标签: Java, 多线程, 同步, 死锁

多线程中,可能出现有两个甚至多个线程试图访问同一个资源的情况,此时,就可能导致资源冲突,引起线程安全的问题。一个经典的例子就是两个人同时对同一个银行账户分别进行存钱取钱的操作。

Java当中,为了使多个线程之间能够安全的共享资源,引入了同步(synchronized)的机制。synchronized可以用在对象的实例方法中,也可以用在类的静态方法中,还可以用于同步语句块中。

1、synchronized实例方法

如下,synchronized关键字用于对象的实例方法中,访问该对象的这些方法时,需要首先获取该对象的锁。

synchronized void f() {
    //
}

synchronized void g() {
    //
}

对于每一个对象来说,都存在一把“锁”,这个锁的信息存放在对象头中。当我们想要调用一个对象的synchronized方法时,必须首先获取这个对象的锁,然后才能调用该方法。而且,当我们获取到了这把锁调用对象的一个synchronized方法时,该对象就会被锁定,此时就无法调用该对象的其他synchronized方法,直到前面一个synchronized方法调用结束,将锁抛出来解除了对该对象的锁定。

例如上面的例子中,在调用了f()之后就不能调用g(),除非f()调用完成了并解除了锁定。

一个特定对象的多个synchronized方法是共享该对象的同一个锁的,这样,就能防止该对象的多个方法同时对通用内存进行读写操作。

如果调用了对象的某一个被synchronized的方法,那么仍然可以调用该对象的其他的未被同步的方法。所以,为了避免线程安全问题,必须对访问某个关键资源的所有方法都进行同步

2、synchronized静态方法

对于synchronized静态方法,它锁的是这个类的Class对象的锁。因此,所有访问同一个类的synchronized静态方法都需要首先获得这个类的Class对象的锁,而与实例方法获取的锁不是同一把。

static synchronized void f() {
    //
}

static synchronized void g() {
    //
}

3、synchronized语句块

另外,除了对一个方法进行同步后,还可以对一个语句块进行同步,例如:

void f() {

    //
    
    synchronized(aObject) {
        //
    }

    //
}

同样的,在进入同步语句块之前,需要获取aObject这个对象的锁,并且,进入了同步块之后,在同步块结束之前,不能调用对象aObject的其他同步方法(同步块)。

上面提到的锁是针对每一个对象实例的。

除此之外,每一个类也有一把锁,它是作为该类的Class对象的一部分。所以,根据类的这把锁,synchronized static方法可以在一个类的范围内被相互锁定起来,防止类的static数据的访问冲突。

然而,为一个方法添加synchronized之后,调用该方法需要额外的代价,因此,不应滥用synchronized,对于已知的不会造成冲突的方法,不应该进行同步


http://www.niftyadmin.cn/n/969291.html

相关文章

Hibernate 延迟加载剖析与代理模式应用

http://www.ibm.com/developerworks/cn/java/j-lo-hibernatelazy/?cmpdwskl&cpbdw&ctdwcon&crcn_51CTO&ccycn转载于:https://blog.51cto.com/774588/836380

在python中使用mysql数据库demo

mysql数据库 版本:mysql Ver 8.0.12 for Win64 on x86_64 (MySQL Community Server - GPL) 0.免密登陆 mysql -u root -p 不输密码直接回车 1.创建表DB、用户scraper1 CREATE DATABASE DB; 创建用户: create user scraper1localhost identified by pa…

RecyclerView用法和源码深度解析

目录介绍 1.RecycleView的结构 2.Adapter 2.1 RecyclerView.Adapter扮演的角色2.2 重写的方法2.3 notifyDataSetChanged()刷新数据2.4 数据变更通知之观察者模式 a.首先看.notifyDataSetChanged()源码b.接着查看.notifyChanged()源码c.接着查看setAdapter()源码中的setAdapter…

容器一:浅析ArrayList源码(JDK1.8)

ArrayList是基于数组实现的List,数组的容量可以改变。ArrayList中允许存放null元素。 ArrayList是unsynchronized的,而Vector是synchronized的。这是两者的主要区别,除此之外两者大致相似。 在ArrayList中,size(), get(),isEmpt…

python-对docx文档操作demo + word批量转pdf 及[AttributeError]解决方案

pip install python-docx 1.读取sample.docx: import docx from docx import Documentfrom pprint import pprintdef getText(filename):doc Document(filename)fullText []for para in doc.paragraphs:fullText.append(para.text)return(fullText)pprint(getText(sample.d…

App测试之Monkey压力测试

转载于:https://www.cnblogs.com/william126/p/10394446.html

IDC简报:4月上旬国外最佳虚拟主机提供商Top5

近日,主机评测机构WebHostingtop最新公布了4月上旬国外最佳虚拟主机提供商。据数据显示,排名前五位的依旧是InMotion、 iPage、FatCow、JustHost和WebHostinghub等知名主机商。下面,IDC评述网与大家一起关注4月上旬国外最佳虚拟主机提供 商To…

python-PyPDF2对pdf的复制 合并demo

pip install PyPDF2 1.copy && merge操作 from PyPDF2 import PdfFileReader , PdfFileWriterfrom PyPDF2 import PdfFileMerger # ---------copy ori_pdf as out_pdf--------------ori_pdf pdf_learn.pdf out_pdf pdf_learn_copy.pdfpdf_input PdfFileReader(open…