奇葩锁

一、改变了锁对象

package com.lanyun.hadoop2;

/**
 * 锁对象的改变问题
 *
 */
public class ChangeLock {

    private String lock = "lock";

    private void method() {
        synchronized (lock) {
            try {
                System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始");
                lock = "change lock";
                Thread.sleep(2000);
                System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {

        final ChangeLock changeLock = new ChangeLock();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                changeLock.method();
            }
        }, "t1");
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                changeLock.method();
            }
        }, "t2");
        t1.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}

本来打算让t1先执行,t1执行完成之后t2再执行,但是t1线程将锁对象改变了,所以可以说t1线程获取的是字符串“lock”的对象锁,t2线程获取的是字符串“change lock”的对象锁。

二、死锁问题

package com.lanyun.hadoop2;
/**
 * 死锁问题,在设计程序时就应该避免双方相互持有对方的锁的情况
 *
 */
public class DeadLock implements Runnable{

    private String tag;
    private static Object lock1 = new Object();
    private static Object lock2 = new Object();
    
    public void setTag(String tag){
        this.tag = tag;
    }
    
    public void run() {
        if(tag.equals("a")){
            synchronized (lock1) {
                try {
                    System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 进入lock1执行");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2) {
                    System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 进入lock2执行");
                }
            }
        }
        if(tag.equals("b")){
            synchronized (lock2) {
                try {
                    System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 进入lock2执行");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 进入lock1执行");
                }
            }
        }
    }
    
    public static void main(String[] args) {
        
        DeadLock d1 = new DeadLock();
        d1.setTag("a");
        DeadLock d2 = new DeadLock();
        d2.setTag("b");
         
        Thread t1 = new Thread(d1, "t1");
        Thread t2 = new Thread(d2, "t2");
         
        t1.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}

三、修改锁对象的属性

package com.lanyun.hadoop2;

/**
 * 同一对象属性的修改不会影响锁的情况
 *
 */
public class ModifyLock {
    
    private String name ;
    private int age ;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    public synchronized void changeAttributte(String name, int age) {
        try {
            System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 开始");
            this.setName(name);
            this.setAge(age);
            
            System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 修改对象内容为: " 
                    + this.getName() + ", " + this.getAge());
            
            Thread.sleep(2000);
            System.out.println("当前线程 : "  + Thread.currentThread().getName() + " 结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        final ModifyLock modifyLock = new ModifyLock();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                modifyLock.changeAttributte("张三", 20);
            }
        },"t1");
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                modifyLock.changeAttributte("李四", 21);
            }
        },"t2");
        
        t1.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}

四、对象锁与类所

package com.lanyun.hadoop2;

/**
 * 使用synchronized代码块加锁,比较灵活
 *
 */
public class ObjectLock {

    public void method1(){
        synchronized (this) {    //对象锁
            try {
                System.out.println("do method1..");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public void method2(){        //类锁
        synchronized (ObjectLock.class) {
            try {
                System.out.println("do method2..");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    private Object lock = new Object();
    public void method3(){        //任何对象锁
        synchronized (lock) {
            try {
                System.out.println("do method3..");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    public static void main(String[] args) {
        
        final ObjectLock objLock = new ObjectLock();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                objLock.method1();
            }
        });
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                objLock.method2();
            }
        });
        Thread t3 = new Thread(new Runnable() {
            public void run() {
                objLock.method3();
            }
        });
        
        t1.start();
        t2.start();
        t3.start();
    }
}

五、使用synchronized代码块减小锁的粒度,提高性能

package com.lanyun.hadoop2;
/**
 * 使用synchronized代码块减小锁的粒度,提高性能
 *
 */
public class Optimize {

    public void doLongTimeTask(){
        try {
            
            System.out.println("当前线程开始:" + Thread.currentThread().getName() + 
                    ", 正在执行一个较长时间的业务操作,其内容不需要同步");
            Thread.sleep(2000);
            
            synchronized(this){
                System.out.println("当前线程:" + Thread.currentThread().getName() + 
                    ", 执行同步代码块,对其同步变量进行操作");
                Thread.sleep(1000);
            }
            System.out.println("当前线程结束:" + Thread.currentThread().getName() +
                    ", 执行完毕");
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        final Optimize otz = new Optimize();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                otz.doLongTimeTask();
            }
        },"t1");
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                otz.doLongTimeTask();
            }
        },"t2");
        t1.start();
        t2.start();
    }
}

六、避免使用字符串对象来做锁

package com.lanyun.hadoop2;

/**
 * synchronized代码块对字符串的锁,注意String常量池的缓存功能
 *
 */
public class StringLock {

    public void method() {
        //new String("字符串常量")
        synchronized ("字符串常量") {
            try {
                while(true){
                    System.out.println("当前线程 : "  + Thread.currentThread().getName() + "开始");
                    Thread.sleep(1000);        
                    System.out.println("当前线程 : "  + Thread.currentThread().getName() + "结束");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        final StringLock stringLock = new StringLock();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                stringLock.method();
            }
        },"t1");
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                stringLock.method();
            }
        },"t2");
        
        t1.start();
        t2.start();
    }
}
原文地址:https://www.cnblogs.com/dongdone/p/5711496.html