java ReentrantLock与synchronized

来源:互联网 发布:前端程序员的技术论坛 编辑:程序博客网 时间:2024/06/05 17:31

synchronized 对象锁

   当多个线程在更新共享状态时避免相互冲突,要保证数据的原子性与可见性,我们通常用synchronized上锁,,一个线程访问synchornied代码库或者方法时,其他线程都将暂时不能访问,知道上一个线程调用的这个synchronized执行完成,才能被另外线程调用,synchronized将自动释放锁,此后另外线程等待到这时才能执行

   例1:并发线程等待

   

package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;public class SynchronizedClass {    private static List<User> userList = new ArrayList<>();    public static void main(String[] args) throws Exception {        new Thread(new Runnable() {            @Override            public void run() {                long startTime= Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + Long.toString(startTime));                addUser();                long endTime=Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime+"  take Time:"+(endTime-startTime));            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                long startTime= Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + startTime);                addUser();                long endTime=Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime+"  take Time:"+(endTime-startTime));            }        }).start();    }    public synchronized static void addUser() {        User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100));        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        userList.add(user);    }}

运行结果:

------->开始执行:thread:13   userSize:0  execute time:1462329339337
------->开始执行:thread:12   userSize:0  execute time:1462329339337
------->结束执行:thread:13   userSize:1  execute time:1462329344348  take Time:5011
------->结束执行:thread:12   userSize:2  execute time:1462329349348  take Time:10011

   例二:当一个线程访问对象锁时或者同步方法 其他线程也能访问非同步方法或非同步代码块

package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;public class SynchronizedClass {    public static class Test {        public void addUser() {            synchronized (this) {                User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100));                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                userList.add(user);            }        }        public synchronized void addUser2() {            User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100));            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            userList.add(user);        }        public void sayHello() {            System.out.println("------->execute time:" + Calendar.getInstance().getTimeInMillis());        }    }    private static List<User> userList = new ArrayList<>();    public static void main(String[] args) throws Exception {       Test t=new Test();        new Thread(new Runnable() {            @Override            public void run() {                long startTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + Long.toString(startTime));                t.addUser();                long endTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime + "  take Time:" + (endTime - startTime));            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                long startTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + startTime);                t.addUser();                long endTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime + "  take Time:" + (endTime - startTime));            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {              t.sayHello();            }        }).start();    }}


运行结果:

------->开始执行:thread:13   userSize:0  execute time:1462330376305
------->开始执行:thread:12   userSize:0  execute time:1462330376305
------->execute time:1462330376305
------->结束执行:thread:13   userSize:1  execute time:1462330381315  take Time:5010
------->结束执行:thread:12   userSize:2  execute time:1462330386315  take Time:10010

在jdk1.5 之后 java还增加了一种锁机制 Lock

   lock的实现类ReentrantLock 比较常用

  ReentrantLock 提供多样化的同步,比如时间限制的同步,可以被interrupt的同步(synchronized的同步是不能interrupt的)等。在资源警政不激烈的情况下,性能稍微比synchronized差点点,反之胜之,据官方称(伴随jvm的提升和优化,差距逐步缩小);reentrantLock还能维持常态:

  注意lock 必须手动释放,不同于synchronized,通常在finally 代码块中(synchronized 出现异常时jvm会自动释放,而lock jvm不会来管理,所以要确保一定释放)

  模板:

Lock lock = new ReentrantLock();        lock.lock();        try {        } finally {            lock.unlock();        }
ReentrantLock 构造方式分为公平锁和非公平锁;synchronized永远是公平的

 /**     * Creates an instance of {@code ReentrantLock}.     * This is equivalent to using {@code ReentrantLock(false)}.     */    public ReentrantLock() {        sync = new NonfairSync();    }    /**     * Creates an instance of {@code ReentrantLock} with the     * given fairness policy.     *     * @param fair {@code true} if this lock should use a fair ordering policy     */    public ReentrantLock(boolean fair) {        sync = fair ? new FairSync() : new NonfairSync();    }
公平情况下:操作会排一个队列按顺序执行,来保证执行的顺序性,同时也会消耗更多的时间

不公平情况下,是无序允许插队的,,jvm会自动计算如何处理更快速度来调度插队,理论更快


ReentrantLock获取锁的4种方式:

1:void lock(); 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁;

2:boolean tryLock(); 如果获取了锁立即返回true,如果别的线程持有锁,立即返回false;

3: boolean tryLock(longtime, TimeUnit unit) throwsInterruptedException;如果获取了锁立即返回true,如果别的线程持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁,立即返回true,如果等待超时,返回false;

4:void lockInterruptibly()throwsInterruptedException;如果获取了锁立即返回,如果没有获取锁,当前线程处于休眠状态,直到当前线程中断



使用场景:防止重复触发:UI疯狂点击,清除无用的临时文件,数据库备份: 建议是用tryLock

                同步执行:防止共享资源的冲突,保证同一个时间段内只有一个操作可以使用该资源,如断点续传,使用lock(),当资源被其他线程锁定,会等待锁释放,继续执行

                已有任务执行,冗长一段时间后 是否可以继续执行 使用tryLock(time),超过这个时间依旧不可以获得锁立即返回false 使用注意事项,这个方法会抛出中断异常

               synchronized与lock在默认情况下是不会相应中断(interrupt)操作,会继续执行完成,lockInterruptibly提供可中断锁来解决此问题

   例3:   lock实例

package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-04 11:09 */public class LockClass {    public static class Test {        Lock lock = new ReentrantLock();        public void addUser() {            try {                lock.lock();                User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100));                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                }                userList.add(user);            } finally {                lock.unlock();            }        }    }    private static List<User> userList = new ArrayList<>();    public static void main(String[] args) throws Exception {        Test t=new Test();        new Thread(new Runnable() {            @Override            public void run() {                long startTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + Long.toString(startTime));                t.addUser();                long endTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime + "  take Time:" + (endTime - startTime));            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                long startTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + startTime);                t.addUser();                long endTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime + "  take Time:" + (endTime - startTime));            }        }).start();    }}
运行结果:
------->开始执行:thread:13   userSize:0  execute time:1462334099726------->开始执行:thread:12   userSize:0  execute time:1462334099726------->结束执行:thread:13   userSize:1  execute time:1462334104736  take Time:5010------->结束执行:thread:12   userSize:2  execute time:1462334109736  take Time:10010

   例4:tryLock实例:

   

package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-04 11:09 */public class LockClass {    public static class Test {        Lock lock = new ReentrantLock();          public void addUser2() {            if (lock.tryLock()) {                try {                    User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100));                    try {                        Thread.sleep(5000);                    } catch (InterruptedException e) {                    }                    userList.add(user);                } finally {                    lock.unlock();                }            }        }    }    private static List<User> userList = new ArrayList<>();    public static void main(String[] args) throws Exception {        Test t = new Test();        new Thread(new Runnable() {            @Override            public void run() {                long startTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + Long.toString(startTime));                t.addUser2();                long endTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime + "  take Time:" + (endTime - startTime));            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                long startTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + startTime);                t.addUser2();                long endTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime + "  take Time:" + (endTime - startTime));            }        }).start();    }}

运行结果:

------->开始执行:thread:13   userSize:0  execute time:1462334850764
------->开始执行:thread:12   userSize:0  execute time:1462334850764
------->结束执行:thread:12   userSize:0  execute time:1462334850773  take Time:9
------->结束执行:thread:13   userSize:1  execute time:1462334855774  take Time:5010                


    例5:tryLock(time)实例:

package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-04 11:09 */public class LockClass {    public static class Test {        Lock lock = new ReentrantLock();             public void addUser3() {            try {                if (lock.tryLock(6, TimeUnit.SECONDS)) {                    try {                        User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100));                        try {                            Thread.sleep(5000);                        } catch (InterruptedException e) {                        }                        userList.add(user);                    } finally {                        lock.unlock();                    }                }            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    private static List<User> userList = new ArrayList<>();    public static void main(String[] args) throws Exception {        Test t = new Test();        new Thread(new Runnable() {            @Override            public void run() {                long startTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + Long.toString(startTime));                t.addUser3();                long endTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime + "  take Time:" + (endTime - startTime));            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                long startTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + startTime);                t.addUser3();                long endTime = Calendar.getInstance().getTimeInMillis();                System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + "   userSize:" + userList.size() + "  execute time:" + endTime + "  take Time:" + (endTime - startTime));            }        }).start();    }}


运行结果:

------->开始执行:thread:13   userSize:0  execute time:1462336448589
------->开始执行:thread:12   userSize:0  execute time:1462336448589
------->结束执行:thread:13   userSize:1  execute time:1462336453600  take Time:5011
------->结束执行:thread:12   userSize:2  execute time:1462336458600  take Time:10011

  例6:

    public void addUser4() {            try {                lock.lockInterruptibly();                User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100));                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                }                userList.add(user);            } catch (InterruptedException e1) {                e1.printStackTrace();            }        }


1 0
原创粉丝点击