`

Java synchronize用法(转)

    博客分类:
  • Java
 
阅读更多

在多个并发线程之间共用资源,就需要进行同步处理。Java虚拟机通过给每个对象加锁的方式实现多线程的同步处理,这里的对象包括类对象和实例对象。一个类的静态成员方法和静态成员域隶属于类对象,一个类的非静态成员域和非静态成员方法隶属于类的实例对象。
   Java 虚拟机为每个对象配备一把锁和一个等候集,对象锁内部锁住的是一些同步方法个同步语句块。一个方法要成为同步方法只要给该方法加上修饰词synchronized就可以了,同步语句块的定义格式为
   synchronized(引用类型的表达式)
其中synchronized是同步语句块的引导词;位于()内的表达式必须是引用类型的表达式。指向某个类对象的实例对象或类对象。即制定与该同步语句相关联的对象;,同步方法和同步语句块都分别于一个特定的对象向关联
    Java虚拟机通过对象的锁确保在任何一个时刻内最多只有一个线程能够运行于该对象相关联的同步方法或同步语句块。对象锁就像闩,它不需要钥匙。当没有线程在运行于该对象相关联的同步方法或同步语句块事对象锁是打开的,这时任何线程都可以进来运行这些于对象向关联的同步方法或同步语句块,但每次只有一个线程进去运行这些代码,一旦有线程进去运行这些与对象相关联的同步方法和同步语句块,对象锁就自动锁上,从而其它需要进去的线程就进入阻塞状态,等待锁的打开,如果线程执行完同步方法或同步语句块并从中退出则对象锁打开。
    在一个方法的前面加上修饰词synchronized该方法就成为同步方法。如果该方法是静态方法,则相应的同步方法会于该方法所在的类对象相关联,受类对象的控制,如果该方法是非静态方法,则相应的同步方法会和该方法所在的类的某个实力对象向关联,受该实例对象锁的控制
    如果多个同步方法与一个对象(类对象或实例对象)相关联,这些同步方法都受这个对象锁的控制。在任何相同的时刻最多有一个线程进入这个同步方法
1、synchronized关键字的作用域有二种:
1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的 synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;

 

synchronized 的语法:
synchronized 可以作为一个method的修饰符,也可以一段代码里出现,先说在代码里出:
  其语法是
   synchronized(xx) {
    //your code
   }
   这个xx需要是一个Object,只要是一个Object就行,如:
        String s="haha";
        synchronized(s) {
           //your code
        }
   不是Object不行,如:
        int n=3;
        synchronized(n) {
                //your code
        }
   是不可以的,有autoboxing也不行。
   如果你理解this的含义,那么
    synchronized(this) {
        //your code
    }
   也很好理解,它需要一个Object,而this是一个特殊的Object,当然可以这样用。
再说synchronized 修饰 method的情况,如果synchronized修饰一个非static的method,
如:
    public synchronized void aMethod() {
        //some code
    }
相当于:
    public void aMethod() {
        synchronized(this) {
           //some code
        }
    }
修饰一个 static的method,
如:
    public static synchronized void aMethod() {
        //some code
    }
相当于:
    public static synchronized void aMethod() {
        synchronized(XX.class) {
           //some code
        }
    }
XX是这个方法所在的类,XX.class 也是一个Object,类型是Class而已,在一个
ClassLoader里,它是唯一的,就是独一无二的object
    总之synchronized的语法可以统一为: synchronized(a var) { do something }


synchronized 的语义:
这是我自己的理解,
   synchronized(xx) {
      //your code
   }
的语义是,在xx这个Object的“授权”、“名义”、 “面子”下,执行 your code。要注
意的是,xx只能授权给一个人(线程),当xx授权给某个人执行后,就不能再授权给别人了
。 当那个人执行完那段代码后,xx才能继续授权给其它人执行,可以理解为,别人在xx的
授权下,执行完这段代码后,把这个权利又还给xx了。 当xx不能授权给一个人时,这个人
必须等在这里,知道xx可以授权给它。 (上面说的人都是线程)


synchronized 的作用:
synchronized是用在多线程环境中的,作用简单的说,就是不允许 “某些” 线程 同时执
行到一段代码里。 这个 “某些”线程 怎么界定? 是由那个xx object决定的,就是当两
个线程执行到 synchronized的时候,需要同一个Object授权时,这两个线程不能同时执行
到需要授权的代码。
  极端情况是 系统你所有的线程都不能执行到这段代码里,那么你就选一个极端唯一的
object作为xx,一般选Class object,如:
synchronized(String.class) {
}

具体到应用比较复杂,举两个例子:
1:

public class Test1 implements Runnable {

    public void run() {
        synchronized(this) {
            try {
                System.out.println("Thread running++++++");
                System.out.println(System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println(System.currentTimeMillis());
                System.out.println("Thread finished++++++");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Test1 test=new Test1();
        for(int i=0;i<10;i++) {
            new Thread(test).start();
        }
    }
}


2:
public class Test1 implements Runnable {

    public void run() {
        synchronized(this) {
            try {
                System.out.println(System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        for(int i=0;i<10;i++) {
            new Thread(new Test1()).start();
        }
    }
}

两个例子中,都有一段synchronized的代码。
在1中,main方法中创建的10个线程 不能同时进入到那段代码执行,因为这10个线程需要让
同一个object授权
而在2中,main方法中创建的10个线程 可以同时进入到那段代码执行,因为10个线程是让不同
的object授权的,均授权成功,同时进入到那段代码执行

 

分享到:
评论

相关推荐

    Java 中synchronize函数的实例详解

    主要介绍了Java 中synchronize函数的实例详解的相关资料,希望通过本文能帮助到大家理解使用synchronize函数的使用方法,需要的朋友可以参考下

    synchronized关键字的用法详解

    synchronized关键字在java中的重要性 以及常用的方法 还有它的详解

    JAVA面试题最全集

    被声明为final的方法也同样只能使用,不能重载 finally?再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。 ...

    synchronized用法大全实例

    java多线程编程核心技术synchronized实例大全,同步方法,同步语句块,类锁,对象锁全都用代码来展现出来

    java 面试题 总结

    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...

    java程序员面试题

    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...

    Java Unsafe类的使用.docx

    CAS算法的出现使得在不使用synchronize这种“悲观锁”依然可以实现数据的安全访问,CAS算法是指先读取要修改的变量值,对它进行计算,然后执行检查并更新这个步骤(更新前判断那个值是否是之前那个读到的值),检查...

    java synchronized 学习

    文章中详细描述了synchronize的使用方法,以及多线程的一些基本使用,纯手打。

    超级有影响力霸气的Java面试题大全文档

    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...

    JAVA面试常考

    文章目录1.HashMap 和 Hashtable的区别2.StringBuilder 和 StringBuffer的区别3.java垃圾...2.Hashtable是线程安全的,效率低,它的每个方法中都加入了Synchronize方法。在多线程并发的环境下,可以直接使用Hashtabl

    关于JAVA面试的100题及其答案

    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...

    MyEclipse10的SVN/Git插件及配置

    (1)MyEclipse10.7.1 (32+64)下载和安装 (2)如何打开MyEclipse10的JS、HTML、Java等各种...(3)对于MyEclipse10导出War包报错问题的解决方法 (4)关于MyEclipse插件git和svn的扩展 若没有积分的朋友,可私聊QQ 1355043929

    进销存系统文档作业例子

    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...

    二十三种设计模式【PDF版】

    设计模式之 Template(模板方法) 实际上向你介绍了为什么要使用 Java 抽象类,该模式原理简单,使用很普遍. 设计模式之 Strategy(策略) 不同算法各自封装,用户端可随意挑选需要的算法. 设计模式之 Chain of ...

    Eclipse权威开发指南2.pdf

    3.2.6 使用快速修正功能来修改Java错误..... 82 3.2.7 重构..... 83 3.2.8 使用代码模板..... 86 3.2.9 字符串外部化..... 87 3.2.10 生成Javadoc.. 88 3.2.11 在不同的JRE下编写 Java代码..... 90 3.2.12 编译...

    Eclipse权威开发指南3.pdf

    3.2.6 使用快速修正功能来修改Java错误..... 82 3.2.7 重构..... 83 3.2.8 使用代码模板..... 86 3.2.9 字符串外部化..... 87 3.2.10 生成Javadoc.. 88 3.2.11 在不同的JRE下编写 Java代码..... 90 ...

    Eclipse权威开发指南1.pdf

    3.2.6 使用快速修正功能来修改Java错误..... 82 3.2.7 重构..... 83 3.2.8 使用代码模板..... 86 3.2.9 字符串外部化..... 87 3.2.10 生成Javadoc.. 88 3.2.11 在不同的JRE下编写 Java代码..... 90 ...

Global site tag (gtag.js) - Google Analytics