java的多线程学习,第五记

 死锁问题;

public class DeadLock {

    //锁的嵌套 会出现死锁
    //1 尽量不要去写锁嵌套
    //2

    private static Object locka = new Object();
    private static Object lockb = new Object();

    public static void main(String[] args) {
        new DeadLock().deadLock();
    }

    private void deadLock() {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (locka){
                    try {
                        System.out.println(Thread.currentThread().getName()+"获取A锁 ing~!");
                        Thread.sleep(500);
                        System.out.println(Thread.currentThread().getName()+"睡眠 500ms!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"需要B锁!!!");
                    synchronized (lockb){
                        System.out.println(Thread.currentThread().getName()+"B锁中!!!");
                    }
                }
            }
        },"thread1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockb){
                    try {
                        System.out.println(Thread.currentThread().getName()+"获取B锁 ing~!");
                        Thread.sleep(500);
                        System.out.println(Thread.currentThread().getName()+"睡眠 400ms!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"需要A锁!!");
                    synchronized (locka){
                        System.out.println(Thread.currentThread().getName()+"A锁中!");
                    }
                }
            }
        },"thread2");

        thread1.start();
        thread2.start();
    }

}
锁的嵌套 会出现死锁
1 尽量不要去写锁嵌套
2 锁嵌套的顺序
3 引入超时机制
显示锁ReentrantLock可重入的锁,我自己的锁可以多次进入。而sync是在jvm层面的。
public class LockTest1 {

    Lock lock = new ReentrantLock();

    private static Object locka = new Object();
    private static Object lockb = new Object();

    public static void main(String[] args) {
        new LockTest1().deadLock();
    }

    private void deadLock() {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                getLock();
            }
        },"thread1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                getLock();
            }
        },"thread2");

        thread1.start();
        thread2.start();
    }

    public void getLock(){
        try{
            lock.lock();
            System.out.println(Thread.currentThread().getName()+"获取A锁 ing~!");
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName()+"睡眠 500ms!");
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}
显示锁ReentrantLock可重入的锁,我自己的锁可以多次进入。而sync是在jvm层面的。
lock.lock()方法是上锁,然后还有在finally里面解锁。这个unlock()方法可能是会锁死的。
或者,用trylock()方法。
if(lock.tryLock(300, TimeUnit.MILLISECONDS)){
                    System.out.println(Thread.currentThread().getName()+"获取A锁 ing~!");
                    Thread.sleep(500);
                    System.out.println(Thread.currentThread().getName()+"睡眠 500ms!");
                }else{
                    //记录日志
                    System.out.println("获取锁失败!");
                }

引入超时机制。还有中断锁lockInterruptibly()。

如果某一线程A正在执行锁中的代码,另一个线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想处理其他的事情,我们可以让它终端自己或者在别的线程中断它,这就是中断锁。

公平锁,非公平锁。sync是非公平的,哪个线程先来都是随机的。公平锁式先来后到,fairLock。但是往往意味着效率低。

public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {

ReentrantReadWriteLock并未实现Lock接口,它实现的是ReadWriteLock接口。

读写锁对一个资源的访问,分成了两个锁,一个读锁和一个写锁。

正因为有了读写锁,才使得多个线程之间的读操作不会发生冲突。

在没有读写锁之前,是通过sync实现的。

public class lockTest {

    private ReentrantReadWriteLock rw1 = new ReentrantReadWriteLock();

    public static void main(String[] args) {
        final lockTest test = new lockTest();

        new Thread(){
            public void run(){
                test.get(Thread.currentThread());
            }
        }.start();

        new Thread(){
            public void run(){
                test.get(Thread.currentThread());
            }
        }.start();
    }

    private synchronized void get(Thread currentThread) {
        long start = System.currentTimeMillis();
        while (System.currentTimeMillis() - start <= 1){
            System.out.println(currentThread.getName()+"正在进行读操作");
        }
        System.out.println(currentThread.getName()+"读操作完毕");
    }

}

而用读锁或者写锁的时候呢,

public class lockTest {

    private ReentrantReadWriteLock rw1 = new ReentrantReadWriteLock();

    public static void main(String[] args) {
        final lockTest test = new lockTest();

        new Thread(){
            public void run(){
                test.get(Thread.currentThread());
            }
        }.start();

        new Thread(){
            public void run(){
                test.get(Thread.currentThread());
            }
        }.start();
    }

//    private synchronized void get(Thread currentThread) {
//        long start = System.currentTimeMillis();
//        while (System.currentTimeMillis() - start <= 1){
//            System.out.println(currentThread.getName()+"正在进行读操作");
//        }
//        System.out.println(currentThread.getName()+"读操作完毕");
//    }

    private void get(Thread currentThread) {
        try{
            //获取一个读锁,再锁上
//            rw1.readLock().lock();
            rw1.writeLock().lock();
            long start = System.currentTimeMillis();
            while (System.currentTimeMillis() - start <= 1){
                System.out.println(currentThread.getName()+"正在进行读操作");
            }
            System.out.println(currentThread.getName()+"读操作完毕");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
//            rw1.readLock().unlock();
            rw1.writeLock().unlock();
        }
    }


}

可以用来提高某些集合的并发性能。当集合比较大,并且读比写频繁时,可以使用该类。

乐观锁和悲观锁。这是数据库层面的锁。

悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次拿数据的时候都会上锁。

乐观锁:每次去拿数据的时候,都认为别人不会上锁,所以不会上锁。

 
 
posted @ 2018-12-21 17:48  正能量教官  阅读(144)  评论(0编辑  收藏  举报