Java的synchronized的使用_Java synchronized的使用

Java synchronized的使用

需要明确的几个问题:

synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果 再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。

无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。

每个对象只有一个锁(lock)与之相关联。

实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

synchronized关键字的作用域有二种:

某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线 程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的 synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;

某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

1、使用在方法上synchronized aMethod(){...}

使用相同的 object

public class synchTest {

private String a= "";

private ListString b= new ArrayList();

// 方法一

public void job() {

System.out.println("job .....");

synchronized (b){

System.out.println("job 使用锁中 ....");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

}

System.out.println("job end.....");

}

// 方法二

public synchronized void job2(){

System.out.println("job2 .....");

synchronized (b){

System.out.println("job22 使用锁中 ...");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

}

System.out.println("job2 end.....");

}

public static void main(String[] args) {

final synchTest rs = new synchTest();

new Thread() {

public void run() {

rs.job();

}

}.start();

new Thread() {

public void run() {

rs.job2();

}

}.start();

}

}

结果:

job .....

job 使用锁中 ....

job2 .....

job end.....

job22 使用锁中 ...

job2 end.....

View Code

使用不同的object

public class synchTest {

private String a= "";

private ListString b= new ArrayList();

// 方法一

public void job() {

System.out.println("job .....");

synchronized (a){

System.out.println("job 使用锁中 ....");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

}

System.out.println("job end.....");

}

// 方法二

public synchronized void job2(){

System.out.println("job2 .....");

synchronized (b){

System.out.println("job22 使用锁中 ...");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

}

System.out.println("job2 end.....");

}

public static void main(String[] args) {

final synchTest rs = new synchTest();

new Thread() {

public void run() {

rs.job();

}

}.start();

new Thread() {

public void run() {

rs.job2();

}

}.start();

}

}

结果:

job .....

job 使用锁中 ....

job2 .....

job22 使用锁中 ...

job end.....

job2 end.....

View Code

使用this关键词

public class synchTest {

private String a= "";

private ListString b= new ArrayList();

// 方法一

public void job() {

System.out.println("job .....");

synchronized (this){

System.out.println("job 使用锁中 ....");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

}

System.out.println("job end.....");

}

// 方法二

public synchronized void job2(){

System.out.println("job2 .....");

synchronized (b){

System.out.println("job22 使用锁中 ...");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

}

System.out.println("job2 end.....");

}

public static void main(String[] args) {

final synchTest rs = new synchTest();

new Thread() {

public void run() {

rs.job();

}

}.start();

new Thread() {

public void run() {

rs.job2();

}

}.start();

}

}

结果:

job .....

job 使用锁中 ....

job end.....

job2 .....

job22 使用锁中 ...

job2 end.....

View Code

结论:

synchronized(Object) object相同的情况下,修饰的内容会同步,等上一个执行完才能执行下一个方法的内容

synchronized(Object)object不相同的情况下,修饰内容不会同步,两个方法可以一起执行

this这个比较特殊,如果先执行修饰this这个方法的内容,会同步,否则 不会同步(可以测试下)

2、使用在方法内部synchronized(Oject){...}

public class synchTest {

// 方法一

public synchronized void job() {

System.out.println("job .....");

System.out.println("job 使用锁中 ....");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

System.out.println("job end.....");

}

// 方法二

public synchronized void job2(){

System.out.println("job2 .....");

System.out.println("job22 使用锁中 ...");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

System.out.println("job2 end.....");

}

public static void main(String[] args) {

final synchTest rs = new synchTest();

new Thread() {

public void run() {

rs.job();

}

}.start();

new Thread() {

public void run() {

rs.job2();

}

}.start();

}

}

结果:

job .....

job 使用锁中 ....

job end.....

job2 .....

job22 使用锁中 ...

job2 end.....

View Code

结论:

对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法,在对象内容所有的synchronized 的方法都会同步,必须等上一个方法执行完才能执行下一个方法

2、使用在方法内部synchronized(Oject){...}、synchronized aMethod(){...}混用

public class synchTest {

public String a = "";

// 方法一

public void job() {

System.out.println("job .....");

synchronized (a){

System.out.println("job 使用锁中 ....");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

}

System.out.println("job end.....");

}

// 方法二

public synchronized void job2(){

System.out.println("job2 .....");

System.out.println("job22 使用锁中 ...");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

System.out.println("job2 end.....");

}

public static void main(String[] args) {

final synchTest rs = new synchTest();

new Thread() {

public void run() {

rs.job();

}

}.start();

new Thread() {

public void run() {

rs.job2();

}

}.start();

}

}

结果:

job .....

job 使用锁中 ....

job2 .....

job22 使用锁中 ...

job end.....

job2 end.....

View Code

结论:

对象实例内synchronized aMethod(){} 与synchronized(Object) 不会相互同步

Java synchronized的使用 相关文章

【Flutter 3-1】Flutter手把手教程UI布局和Widget——底部导航栏BottomNavigationBar使用

作者 | 弗拉德 来源 | 弗拉德(公众号:fulade_me) BottomNavigationBar BottomNavigationBar 和 BottomNavigationBarItem 配合来共同展示Flutter里面的底部状态栏,底部状态栏是在移动端很重要的控件。 先看一下 BottomNavigationBar 构造方法 BottomNaviga

Java序列化,看这篇就够了

1.什么是序列化 Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程: 序列化: 对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在

如何获取指定模块下所有的类

前言 在使用 scrapy 时,运行爬虫仅需要通过 scrapy crawl 爬虫名 就可启动我们写好的爬虫,那么 scrapy 是如何通过名称找到爬虫类的呢通过分析源码可窥见一二,同时也可从中找出获取指定模块下的所有类的方法。 scrapy 源码分析 在 scrapy.spiderloader.Spi

SpringBoot配置文件说明

1.简介 在使用SpringBoot的时候肯定听说过SpringBoot可以做到零配置,其实创建SpringBoot确实可以做到零配置,它在内部其实帮你默认配置基础的参数,但是它确实配置方便,所以集成的配置参数都可以在SpringBoot提供的配置文件中自己设置,除了在SpringBoot提

Qt中的QThread:使用QSemaphore进行多线程数据同步

20210127:在生产者、消费者的方法中添加线程挂起方法QThread::usleep(10),使ui不卡。 20210128:在添加Track类(保存生产者Producer生成的每组数据),在ui界面中使用model-view同步显示生产者生成的数据,model-view不会对主线程造成卡顿。对消费者同样创

SpringBoot使用JSR303校验数据

JSR303是java提供的一套用来校验数据的规范 SpringBoot使用JSR303校验数据 javax.validation.constraints 使用方式: 在Entity实体类上加上相应的注解,并定义自定义message(错误提示) @Valid 启用校验 数据验证不通过: 状态码:400 可以在需要校验的对象后

SpringBoot-dev-tools的使用

spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot应用。 在项目中添加 spring-boot-devtools 非常简单,只需要添加以下依赖项即可: maven dependencies dependency g

JavaScript数据类型转换

目录 前言 一、强制转换 1、其他的数据类型转换为String 方式一:toString()方法 方式二:String()函数 2、其他的数据类型转换为Number 方式一:使用Number()函数 方式二:parseInt() parseFloat() 3、其他的数据类型转换为Boolean 二、自动转换 1.自动转换

Go语言中的指针

与 Java 和 .NET 等编程语言不同,Go语言为程序员提供了控制数据结构指针的能力,但是,并不能进行指针运算。Go语言允许你控制特定集合的数据结构、分配的数量以及内存访问模式,这对于构建运行良好的系统是非常重要的。指针对于性能的影响不言而喻,如果你

JavaScript给对象赋值的两种方式

在JavaScript的基础语法中,我们必定会用到Object这种数据类型,给这种数据类型的属性赋值的方式有两种....... . 赋值的方式 var obj = { name: 'TOM', age: 18}obj.name = "Jack" 这应该是大家最常用的一种方式了,但是这种方式在有些特殊时候并不能够使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值