• synchronized一个(二)


    今天遇到了一个关于synchronized的一个问题,关于其持有锁的问题。这个问题以前是有看过相关文章的,但是一直没有记录,今天大概记录一下当前的认知。

    对于静态方法,synchronized的使用的锁实际上是以Class对象作为锁,对于非静态方法,持有的锁为方法所在的对象。可能有点难以理解,但是,仔细想想,静态方法是类级别的,而非静态方法属于对象级别的。这样或许好理解一下。

    关于synchronized的常规用法

    同步控制块。进入此段代码前,必须得到syncObject对象的锁,如果其他线程正在持有这个锁,那么就得等到这个线程释放以后,才能进入临界区。

    synchronized(syncObject){
      //处理逻辑
    }
    

    亦或使用其修饰整改方法,这个时候,就需要注意到开头说的锁的问题了。对于不同级别的方法,所持有的锁是不同的。

    synchronized fun(){
      //处理逻辑
    }
    

    下面我们,通过demo来说这个情况。注释代码,说明了静态方法与非静态方法使用不同的锁。三个线程并发,为了说明即使在同一个对象当中,也必须使用相同的对象锁,synchronized才能确保临界区同一个时刻只能被一个线程访问。结果中先输出fun2表明线程2并没有因线程1持有当前demo对象的锁而被阻塞,但是线程3却被阻塞了。

    package com.woniu.test.concurrency;
    
    import java.util.HashMap;
    import java.util.concurrent.ScheduledThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class TestSynchronized {
    
        public static void main(String[] args) throws InterruptedException {
    //        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
    //        executor.scheduleAtFixedRate(new Demo(), 1, 2, TimeUnit.SECONDS);
    //        
    //        while(true) {
    //            System.out.println(System.currentTimeMillis() + ", woniu id is " + Demo.getMap().get("woniu"));
    //            Thread.sleep(1000);//这里的延迟会因updateMap持有相同的锁,导致延迟的时间变得更长
    //        }
            
            final Demo demo = new Demo();
            
            new Thread(new Runnable() {
                
                public void run() {
                    try {
                        demo.fun1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    
                }
            }
            ).start();
            
            Thread.sleep(1000);
            new Thread(new Runnable() {
                
                public void run() {
                    try {
                        demo.fun2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    
                }
            }
            ).start();
            
            new Thread(new Runnable() {
                
                public void run() {
                    try {
                        demo.fun3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    
                }
            }
            ).start();
        }
    }
    
    class Demo implements Runnable {
    
        private static HashMap<String, Integer> map = new HashMap<String, Integer>();
        private Object obj = new Object();
        public Demo() {
            map.put("woniu", 1);
        }
        
        public void run() {
            try {
                updateMap();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        //如果updateMap没有使用static进行修饰,此处休息3000ms,对于主线程的while循环式不起作用的,因为两者使用的锁不一致。
        public synchronized static void updateMap() throws InterruptedException {
            System.out.println("begin to update");
            Thread.sleep(3000);
            map.put("woniu", map.get("woniu") + 1);
            System.out.println("update end");
        }
        
        public synchronized static HashMap<String, Integer> getMap() {
            return map;
        }
        
        
        public synchronized void fun1() throws InterruptedException {
            Thread.sleep(3000);
            System.out.println("this is fun1()");
        }
        
        public void fun2() throws InterruptedException {
            synchronized (obj) {
                System.out.println("this is fun2()");
            }
        }
        
        public void fun3() throws InterruptedException {
            synchronized (this) {
                System.out.println("this is fun3()");
            }
        }
    }
  • 相关阅读:
    pl sql 编程
    maven(一) maven到底是个啥玩意~
    Oracle 数据库管理员
    Oracle 常用函数
    Oracle 事务
    Oracle 分页
    java String类
    java 方法
    java 数组
    java 跨平台 数据类型 修饰符 程序结构
  • 原文地址:https://www.cnblogs.com/woniu4/p/9292070.html
Copyright © 2020-2023  润新知