JAVA 同步之 synchronized 修饰方法

在JAVA多线程编程中,将需要并发执行的代码放在Thread类的run方法里面,然后创建多个Thread类的对象,调用start()方法,线程启动执行。

当某段代码需要互斥时,可以用 synchronized 关键字修饰,这里讨论 synchronized 关键字修饰方法时,是如何互斥的。

synchronized 修饰方法时锁定的是调用该方法的对象。它并不能使调用该方法的多个对象在执行顺序上互斥。

下面举个具体的例子说明:

Test.java 通过 implements Runnable 成为一个线程类,它有一个MethodSync实例变量,这样,每当实例化一个Test对象时(相当于创建一个线程)就会初始化一个相应的MethodSync对象。然后在run()方法里面调用 synchronized 修饰的方法。

Test.java

 1 public class Test implements Runnable{
 2     private String name;
 3 //    private static MethodSync methodSync = new MethodSync();
 4     private MethodSync methodSync = new MethodSync();
 5
 6     public Test(String name){
 7         this.name = name;
 8     }
 9
10     @Override
11     public void run() {
12         methodSync.method(name);
13     }
14
15     public static void main(String[] args) {
16         Thread t1 = new Thread(new Test("test 1"));
17         Thread t2 = new Thread(new Test("test 2"));
18         t1.start();
19         t2.start();
20     }
21 }

MethodSync.java ,该类只拥有一个用来测试的 synchronized 方法

 1 public class MethodSync {
 2
 3     /*
 4      * @Task : 测试 synchronized 修饰方法时锁定的是调用该方法的对象
 5      * @param name  线程的标记名称
 6      */
 7     public synchronized void method(String name){
 8         System.out.println(name + " Start a sync method");
 9         try{
10             Thread.sleep(300);
11         }catch(InterruptedException e){}
12         System.out.println(name + " End the sync method");
13     }
14 }

先看执行结果:

test1 先于 test2 执行 同步方法,但是却后于 test2 结束。这里并没有达到互斥的效果!原因是:MethodSync是实例变量,每次创建一个Test对象就会创建一个MethodSync对象, synchronized 只会锁定调用method()方法的那个MethodSync对象,而这里创建的两个线程分别拥有两个不同的MethodSync对象,它们调用method方法时就没有互斥关系。

当把Test.java 中的MethodSync 变量 用 static 来修饰时,执行结果如下:

这里,正确实现了同步作用。原因如下:这里也创建了二个线程(Test 对象),但是每个Test对象共享MethodSync 变量,也即只有一个MethodSync 变量在两个线程中执行 method方法,这样两个线程在执行到method 方法这段代码时就会形成互斥。

时间: 2024-12-23 11:22:36

JAVA 同步之 synchronized 修饰方法的相关文章

synchronized修饰方法和对象的区别

使用synchronized(object) { 代码块.... } 能对代码块进行加锁,不允许其他线程访问,其的作用原理是:在object内有一个变量,当有线程进入时,判断是否为0,如果为0,表示可进入执行该段代码,同时将该变量设置为1,这时其他线程就不能进入:当执行完这段代码时,再将变量设置为0. 想保证代码块在任务情况下都同步,即代码块在程序的中同一时刻只被一个线程调用,即需要使用synchronized( static object). object必须是静态变量,否则不同对象调用该方法

一张图讲解对象锁和关键字synchronized修饰方法

每个对象在出生的时候就有一把钥匙(监视器),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题. 下面通过一张图片进行讲解: 1.一张图片 图片看不清,请右键 ,新标页面打开查看大图 这里写图片描述 2.图片对应的代码 import java.util.Date; /** * 测试的object类 * * @author:dufy * @version:1.0.0 * @date 2017/9/29 * @email [

一张图讲解对象锁和关键字synchronized修饰方法(代码块)

每个对象在出生的时候就有一把钥匙(监视器Monitor),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题. 注:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁.每一个对象都有,也仅有一个 Monitor. 下面通过一张图片进行讲解:1.一张图片图片看不清,请点击这里 : 高清大图这里写图片描述2.图片对应的代码/*** 测试的object类**/}}}}}}1

Java语言中synchronized 修饰在 static方法和 非static方法的区别(转)

synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了. 那么,在static方法和非static方法前面加synchronized到底有什么不同呢? 大家都知道,static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,就是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了).而非stat

java同步代码(synchronized)中使用BlockingQueue

说起BlockingQueue,大家最熟悉的就是生产者-消费者模式下的应用.但是如果在调用queue的上层代码加了同步块就会导致线程死锁. 例如: static BlockingQueue<String> queue = new LinkedBlockingQueue(); /** * 同步锁 */ static Object lock = new Object(); static void producer(){ synchronized (lock){ queue.put("1&

JAVA之线程同步的三种方法

最近接触到一个图片加载的项目,其中有声明到的线程池等资源需要在系统中线程共享,所以就去研究了一下线程同步的知识,总结了三种常用的线程同步的方法,特来与大家分享一下.这三种方法分别是:synchronized代码段.synchronized修饰方法/类.ThreadLocal本地线程变量. 我们通过一个例子来表现这三种方法:一张银行卡里面有300块钱,15个线程从这张银行卡中取钱,每个线程取一次且每次取20块钱:当当前余额不足100元时,则向账户中汇款20元.三种方法每种方法都有5个线程.我们预期

深入理解java同步、锁机制

本片文章尝试从另一个层面来了解我们常见的同步(synchronized)和锁(lock)机制.如果读者想深入了解并发方面的知识推荐一本书<java并发编程实战>,非常经典的一本书,英语水平好的同学也可以读一读<Concurrent programming in Java - design principles and patterns>由Doug Lea亲自操刀,Doug Lea是并发方面的大神,jdk的并发包就是由他完成的. 我们都知道在java中被synchronized修饰的

Java同步问题面试参考指南

同步 在多线程程序中,同步修饰符用来控制对临界区代码的访问.其中一种方式是用synchronized关键字来保证代码的线程安全性.在Java中,synchronized修饰的代码块或方法不会被多个线程并发访问.它强制要求线程在进入一个方法之前获得一个锁,在离开方法时释放该锁.它保证了在同一时刻只有一个线程能执行被其修饰的方法. 如果我们把一个方法或代码块定义为同步的,就意味着在同一个对象中,只会有一个对同步方法的调用.如果在一个线程内部调用了一个同步方法,则其他线程会一直阻塞,直到第一个线程完成

深入了解java同步、锁紧机构

该薄膜还具有从本文试图一个高度来认识我们共同的同步(synchronized)和锁(lock)机制. 我们假定读者想了解更多的并发知识推荐一本书<java并发编程实战>,这是一个经典的书,英语水平良好的学生也可以读<Concurrent programming in Java - design principles and patterns>由Doug Lea亲自操刀.Doug Lea是并发方面的大神,jdk的并发包就是由他完毕的. 我们都知道在java中被synchronized