zoukankan      html  css  js  c++  java
  • synchronized关键字修饰非静态方法与静态方法的区别

    这里我们先创建ObjLock类,并实现Runnable接口。并创建一个Demo类,具有被synchronized关键字修饰的非静态方法与静态方法。

    非静态方法

    public class ObjLock implements Runnable {
    
        Demo demo;
    
        public ObjLock(Demo demo){
            this.demo = demo;
        }
    
        public void run() {
            demo.getI(Thread.currentThread().getName());
        }
    
        public static void main(String[] args){
            Demo demo = new Demo(1);
            Thread thread = new Thread(new ObjLock(demo),"thread0");
            Thread thread1 = new Thread(new ObjLock(demo),"thread1");
            Thread thread2 = new Thread(new ObjLock(new Demo(2)),"thread2");
            thread.start();
            thread1.start();
            thread2.start();
        }
    }
    
    
    class Demo{
    
        static int i;
    
        Demo(int i){
            this.i=i;
        }
    
        public static synchronized void staticGetI(String s){
            for (int j=0;j<10000;j++){
                System.out.println(i+"---------"+s);
            }
        }
    
        public synchronized void getI(String s){
            for (int j=0;j<10000;j++){
                System.out.println(i+"---------"+s);
            }
        }
    }

    运行程序,可以看到如下结果:

    1---------thread0
    1---------thread0
    2---------thread2
    1---------thread0
    2---------thread2
    1---------thread0
    1---------thread1
    1---------thread1
    2---------thread2
    1---------thread1
    1---------thread1
    1---------thread1

    可以看到Thread0和Thread2交替出现,Thread1和Thread2交替出现,但Thread0和Thread1不会交替出现。

    因为对非静态方法加锁,实际上是对调用该方法的对象加锁。Thread0和Thread1用的是同一个对象,所以互斥,但是Thread2则不受影响。

    静态方法

    将getI方法改成static之后

    public void run() {
        demo.staticGetI(Thread.currentThread().getName());
    }

    测试发现三个线程均互斥。

    当synchronized修饰一个static方法时,多线程下,获取的是类锁(即Class本身,注意:不是实例),作用范围是整个静态方法,作用的对象是这个类的所有对象。

    一个对象在两个线程中分别调用一个静态同步方法和一个非静态同步方法

    修改代码

    public void run() {
        if (Thread.currentThread().getName().equals("thread0")){
            demo.staticGetI(Thread.currentThread().getName());
        }else if (Thread.currentThread().getName().equals("thread1")){
            demo.getI(Thread.currentThread().getName());
        }
    } 

    结果:不会产生互斥。

    解释:因为虽然是一个对象调用,但是两个方法的锁类型不同,调用的静态方法实际上是类对象在调用,即这两个方法产生的并不是同一个对象锁,因此不会互斥,会并发执行。

  • 相关阅读:
    sencha touch 视图(view) activate与deactivate事件探讨
    sencha touch Demo(示例)(2014-6-25)
    sencha touch NavigationView 源码详解(注释)
    sencha touch Model validations(模型验证,自定义验证)
    sencha touch routes(路由) 传递中文参数
    第二步 使用Cordova 3.0(及以上版本) 创建安卓项目(2014-6-25)
    sencha touch datepicker/datepickerfield(时间选择控件)扩展(废弃 仅参考)
    sencha touch list ListPaging使用详解
    sencha touch list更新单行数据
    sencha touch list tpl 监听组件插件(2013-9-15)
  • 原文地址:https://www.cnblogs.com/chongaizhen/p/10972747.html
Copyright © 2011-2022 走看看