美文网首页
并发编程(九):多线程问题

并发编程(九):多线程问题

作者: codeMover | 来源:发表于2020-04-18 10:33 被阅读0次

线程安全导致效率降低

采用多把锁方式

采用多把锁的前提,是两个共享资源之前没有关联性。

  • 好处:可以增强并发度
  • 坏处:如果一个线程需要同时获得多把锁,容易产生死锁

线程安全带来线程活跃性问题

死锁

  • 一个线程需要同时获取多吧锁,容易产生死锁
    • 线程1已经获得锁A,需要获得锁B
    • 线程2已经获得锁B,需要获得锁A
  • 可以采取顺序加锁方式,解决线程死锁问题
  • 检测定位死锁
    • jconsole
    • jstack
  • 典型问题:哲学家就餐
public class PhilosopherProblem {
    public static void main(String[] args) {
        Chopstic c1 = new Chopstic("1");
        Chopstic c2 = new Chopstic("2");
        Chopstic c3 = new Chopstic("3");
        Chopstic c4 = new Chopstic("4");
        Chopstic c5 = new Chopstic("5");

        new Philosopher("苏格拉底",c1,c2).start();
        new Philosopher("泊拉图",c2,c3).start();
        new Philosopher("亚里士多德",c3,c4).start();
        new Philosopher("阿基米德",c4,c5).start();
        new Philosopher("米开朗琪罗",c5,c1).start();
    }
}

@Slf4j(topic = "ants.Philosopher")
class Philosopher extends Thread{
    Chopstic left;
    Chopstic right;

    public Philosopher(String name,Chopstic left,Chopstic right){
        super(name);
        this.left = left;
        this.right = right;
    }

    @SneakyThrows
    @Override
    public void run() {
        while (true){
            synchronized (left){
                synchronized (right){
                    eat();
                }
            }
        }
    }
    private void eat() throws InterruptedException {
        log.debug("eating...");
        Thread.sleep(1000);
    }
}


class Chopstic{
    private String name;
    public Chopstic(String name){
        this.name = name;
    }

    @Override
    public String toString() {
        return "筷子:【"+name+"】";
    }
}
线程执行一段时间后不再向下执行,这时候发生死锁,分析如下

使用jps查看线程

...... jps
593 Launcher
594 PhilosopherProblem
548 
621 Jps

使用jstack 594查看线程运行情况,发现死锁

Found one Java-level deadlock:

活锁

  • 两个线程,互相修改对方的结束条件
  • 解决活锁:破坏活锁发生条件,例如随机的随眠时间
@Slf4j(topic = "ants.LiveLock")
public class LiveLock {
    static volatile int i=10;

    public static void main(String[] args) {
        new Thread("t1"){
            boolean flag = true;
            @Override
            public void run() {
                while (true){
                    log.debug(i+"");
                    i--;
                    if(i==0){
                        flag=false;
                        log.debug("线程1执行完毕");
                    }
                }
            }
        }.start();

        new Thread("t2"){
            boolean flag = true;
            @Override
            public void run() {
                while (true){
                    log.debug(i+"");
                    i++;
                    if(i==20){
                        flag=false;
                        log.debug("线程2执行完毕");
                    }
                }
            }
        }.start();
    }
}

饥饿

  • 一个线程由于优先级太低,始终得不到CPU调度执行,不能够结束

相关文章

网友评论

      本文标题:并发编程(九):多线程问题

      本文链接:https://www.haomeiwen.com/subject/vcgmvhtx.html