Java 中synchronize函数的实例详解

Java 中synchronize函数的实例详解

java中的一个类的成员函数若用synchronized来修饰,则对应同一个对象,多个线程像调用这个对象的这个同步函数时必须等到上一个线程调用完才能由下一个线程调用。

那么如果一个类同时有两个成员函数是由synchronized修饰如代码所示,对与同一个对象,是否可以在两个线程运行时,一个调用funcA,同时另一个调用funcB?

Mysyn是这样一个类,如果我有两个线程,一个在run方法中先运行funcA再运行funcB,另一个线程在run方法中先运行funcB再运行funcA。那有没有可能出现这样的情况:在输出时start A...后面直接输出start B...?

public class MySyn {
  public synchronized void funcA(String str){
    System.out.println(str+":");
    System.out.println("start A...");
    try {
      Thread.sleep(5000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    System.out.println("...A end");
  } 

  public synchronized void funcB(String str){
    System.out.println(str+":");
    System.out.println("start B...");
    try {
      Thread.sleep(5000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    System.out.println("...B end");
  }
}

测试代码如下:

这个线程是先运行funcA的

public class Mythread implements Runnable { 

  private MySyn mysyn;
  private String id;
  public Mythread(MySyn syn, String id){
    this.mysyn = syn;
    this.id = id;
  }
  @Override
  public void run() { 

    this.mysyn.funcA(id);
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    this.mysyn.funcB(id);
  } 

  public static void main(String arg[]){
    MySyn syn=new MySyn();
    Thread t1 = new Thread(new Mythread(syn, "t1"));
    Thread t2 = new Thread(new YourThread(syn, "t2")); 

    t1.start();
    t2.start();
  } 

}

这个线程是先运行funcB的

public class YourThread implements Runnable { 

  private MySyn mysyn;
  private String id;
  public YourThread(MySyn syn, String id){
    this.mysyn = syn;
    this.id=id;
  }
  @Override
  public void run() {
    this.mysyn.funcB(id);
    this.mysyn.funcA(id); 

  } 

}

输出结果多是:

t1:
start A...
...A end
t2:
start B...
...B end
t2:
start A...
...A end
t1:
start B...
...B end

如果取消Mythread的run方法中两个函数调用间的sleep,那结果多是:

t1:
start A...
...A end
t1:
start B...
...B end
t2:
start B...
...B end
t2:
start A...
...A end

个人结果可能因线程调度不同,但是永远不会有:start A...后面直接输出start B...

那如果funcB不是一个同步函数,那上述代码运行结果会是怎么样呢?

代码稍加改动,把funcB的synchronized关键字去掉。运行结果为:

t2:
t1:
start A...
start B...
...A end
t1:
start B...
...B end
t2:
start A...
...B end
...A end

显然出现了start A...后面直接输出start B...的结果。

同样如果Mysyn类如果有一个public 的成员变量,多线程也可以再同步函数被调用的同时,由另一个线程修改这个成员变量。

上述实验说明了:同步的成员函数只能在同一个对象的同步函数调用中对其他同步函数(包括本身)有排它的效果,即多线程运行中,同一个对象当前只能有一个同步函数在运行,但不排除其他非同步函数的运行或对成员进行访问。

那现在假设某个类有两个静态同步方法,那情况怎么样呢?

具体实现,我就不重复了,因为结果类似:

在多线程中,同一个类,当前只能有一个类同步函数(静态同步函数)在运行,但不排除其他非同步静态函数的运行或对静态成员的访问

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Java 同步锁(synchronized)详解及实例

    Java 同步锁(synchronized)详解及实例 Java中cpu分给每个线程的时间片是随机的并且在Java中好多都是多个线程共用一个资源,比如火车卖票,火车票是一定的,但卖火车票的窗口到处都有,每个窗口就相当于一个线程,这么多的线程共用所有的火车票这个资源.如果在一个时间点上,两个线程同时使用这个资源,那他们取出的火车票是一样的(座位号一样),这样就会给乘客造成麻烦.比如下面程序: package com.pakage.ThreadAndRunnable; public class Ru

  • Java中synchronized关键字修饰方法同步的用法详解

    Java的最基本的同步方式,即使用synchronized关键字来控制一个方法的并发访问. 每一个用synchronized关键字声明的方法都是临界区.在Java中,同一个对象的临界区,在同一时间只有一个允许被访问. 静态方法则有不同的行为.用synchronized关键字声明的静态方法,同时只能够被一个执行线程访问,但是其他线程可以访问这个对象的非静态的synchronized方法.必须非常谨慎这一点,因为两个线程可以同时访问一个对象的两个不同的synchronized方法,即其中一个是静态s

  • Java多线程程序中synchronized修饰方法的使用实例

    在Java 5以前,是用synchronized关键字来实现锁的功能. synchronized关键字可以作为方法的修饰符(同步方法),也可作用于函数内的语句(同步代码块). 掌握synchronized,关键是要掌握把那个东西作为锁.对于类的非静态方法(成员方法)而言,意味着要取得对象实例的锁:对于类的静态方法(类方法)而言,要取得类的Class对象的锁:对于同步代码块,要指定取得的是哪个对象的锁.同步非静态方法可以视为包含整个方法的synchronized(this) { - }代码块.  

  • Java关键字volatile和synchronized作用和区别

    volatile是变量修饰符,而synchronized则是作用于一段代码或方法:如下三句get代码: int i1; int geti1() {return i1;} volatile int i2; int geti2() {return i2;} int i3; synchronized int geti3() {return i3;} geti1() 得到存储在当前线程中i1的数值.多个线程有多个i1变量拷贝,而且这些i1之间可以相互不同.换句话说,另一个线程可能已经改变了它线程内的i1

  • 实例解析Java中的synchronized关键字与线程安全问题

    首先来回顾一下synchronized的基本使用: synchronized代码块,被修饰的代码成为同步语句块,其作用的范围是调用这个代码块的对象,我们在用synchronized关键字的时候,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步.这叫减小锁的粒度,使代码更大程度的并发. synchronized方法,被修饰的方法成为同步方法,其作用范围是整个方法,作用对象是调用这个方法的对象. synchronized静态方法,修饰一个static静态方法,其作用范围是整个

  • java synchronized同步静态方法和同步非静态方法的异同

    java synchronized 详解 synchronized关键字有两种用法,一种是只用于方法的定义中,另外一种是synchronized块,我们不仅可以使用synchronized来同步一个对象变量,你也可以通synchronizedl来同步类中的静态方法和非静态方法. synchronized块的语法如下: public void method() { synchronized(表达式) { } } public void method() { synchronized(表达式) {

  • java中synchronized(同步代码块和同步方法)详解及区别

     java中synchronized(同步代码块和同步方法)详解及区别 问题的由来: 看到这样一个面试题: //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized (obj){} } synchronized用于解决同步问题,当有多条线程同时访问共享数据时,如果进行同步,就会发生错误,Java提供的解决方案是:只要将操作共享数据的语句在某一时段让一个线程执行完,在执行过程中,其他

  • Java 中synchronize函数的实例详解

    Java 中synchronize函数的实例详解 java中的一个类的成员函数若用synchronized来修饰,则对应同一个对象,多个线程像调用这个对象的这个同步函数时必须等到上一个线程调用完才能由下一个线程调用. 那么如果一个类同时有两个成员函数是由synchronized修饰如代码所示,对与同一个对象,是否可以在两个线程运行时,一个调用funcA,同时另一个调用funcB? Mysyn是这样一个类,如果我有两个线程,一个在run方法中先运行funcA再运行funcB,另一个线程在run方法

  • Java 中This用法的实例详解

     Java 中This用法的实例详解 用类名定义一个变量的时候,定义的只是一个引用,外面可以通过这个引用来访问这个类里面的属性和方法. 那们类里面是够也应该有一个引用来访问自己的属性和方法纳? 呵呵,Java提供了一个很好的东西,就是 this 对象,它可以在类里面来引用这个类的属性和方法.先来个简单的例子: public class ThisDemo { String name="Mick"; public void print(String name){ System.out.pr

  • java 中自定义OutputFormat的实例详解

    java 中 自定义OutputFormat的实例详解 实例代码: package com.ccse.hadoop.outputformat; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apa

  • java中的interface接口实例详解

     java中的interface接口实例详解 接口:Java接口是一些方法表征的集合,但是却不会在接口里实现具体的方法. java接口的特点如下: 1.java接口不能被实例化 2.java接口中声明的成员自动被设置为public,所以不存在private成员 3.java接口中不能出现方法的具体实现. 4.实现某个接口就必须要实现里面定义的所有方法. 接下来看一个实现接口的案例: package hello;   interface competer{ //定义接口 void set_comp

  • java中Spring Security的实例详解

    java中Spring Security的实例详解 spring security是一个多方面的安全认证框架,提供了基于JavaEE规范的完整的安全认证解决方案.并且可以很好与目前主流的认证框架(如CAS,中央授权系统)集成.使用spring security的初衷是解决不同用户登录不同应用程序的权限问题,说到权限包括两部分:认证和授权.认证是告诉系统你是谁,授权是指知道你是谁后是否有权限访问系统(授权后一般会在服务端创建一个token,之后用这个token进行后续行为的交互). spring

  • Java中的动态和静态编译实例详解

    Java中的动态和静态编译实例详解 首先,我们来说说动态和静态编译的问题. Q: java和javascript有什么区别?    总结了一下:有以下几点吧: 1.首先从运行环境来说java代码是在JVM上编译成class文件,而javascript则直接在浏览器上加载运行. 2.由第一点可看出,java代码需要编译,而javascript不需要编译. 3.从语言性质来说,java是一种高级编程语言,对变量检查要求严格,javascript只是一个简单的解释性的脚本语言,对变量检查及要求很弱.

  • java 中createStatement()方法的实例详解

    java 中createStatement()方法的实例详解 用缺省设置创建时,ResultSet 是一种只能访问一次(one-time-through).只能向前访问(forward-only)和只读的对象.您只能访问数据一次,如果再次需要该 数据,必须重新查询数据库. 然而,并不只有这一种方式.通过设置 Statement 对象上的参数,您可以控制它产生的 ResultSet.例如: ... Class.forName(driverName); db = DriverManager.getC

  • Java中IO流 字节流实例详解

    Java中IO流 字节流实例详解 IO流(输入流.输出流),又分为字节流.字符流. 流是磁盘或其它外围设备中存储的数据的源点或终点. 输入流:程序从输入流读取数据源.数据源包括外界(键盘.文件.网络-),即是将数据源读入到程序的通信通道. 输出流:程序向输出流写入数据.将程序中的数据输出到外界(显示器.打印机.文件.网络-)的通信通道. 字节流 1.InputStream.OutputStream InputStream抽象了应用程序读取数据的方式 OutputStream抽象了应用程序写出数据

  • java 中死锁问题的实例详解

    java 中死锁问题的实例详解 先看代码在做解释 public class DeadLock implements Runnable{ String a; String b; boolean flag; public DeadLock(String a,String b,boolean flag){ this.a=a; this.b=b; this.flag=flag; } public void run(){ if(flag){ // while(true){ synchronized(a){

  • java 中@Deprecated 注解的实例详解

    java 中@Deprecated 注解的实例详解 1 简介 Deprecated 同 SuppressWarnings 一样,都是 J2SE 5.0 中定义在Java.lang包中的标准 Annotation 之一,其可以标注在类.字段和方法上,其作用为:不鼓励程序员使用被 @Deprecated 注释的程序元素,因为被 @Deprecated 注释的元素很危险(例如,现阶段 JDK 提供的带有 @Deprecated 注释的元素在以后的 JDK 版本中可能被删除)或存在更好的选择.在使用不被

随机推荐