美文网首页
synchronized 、volatile 、线程通信基础、T

synchronized 、volatile 、线程通信基础、T

作者: 耗子撼大象 | 来源:发表于2017-09-28 17:09 被阅读0次

    synchronized单个对象多个线程问题

    分析: 当多个线程访问线程类的run方法时,以排队的方式进行处理(通过cpu安排,而不是通过代码的顺序)
    1: 尝试获得锁
    2: 如果拿到锁,执行synchronized代码块内容,拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,这样会出现多个线程同时去竞争这把锁。(也就会有锁竞争问题,比如上千个线程同时访问,就会造成cpu使用率一下增加)。

    synchronized 多个对象多个线程问题

    对于多个多线程多个对象,如果要实现访问synchronized修饰的方法,如果实现同时只有一个线程执行该方法,需要在该方法加static ,此时synchronized属于类级方法。

    public static synchronized void print(String tag){
        try{
        if (tag.equals("a")) {
            num = 100;
            System.out.println("tag a 赋值成功");
            Thread.sleep(1000);
        }else{
            num = 200;
            System.out.println("tag "+tag+" 赋值成功");
        }
        System.out.println("tag "+ tag+" num 为"+ num);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    

    volatile

    1: volatile 主要修饰变量让多个线程间透明,比如,一个变量a = 0,线程A 要把a赋值为10 ,线程B 要把a 赋值为20 ,当线程A修改成10 之后,线程B还是从0 修改成20 ,如果在变量名前面加上volatile,数据就保持一致性,线程B修改的是a此时为10,让线程A和B都保持了透明。
    2: volatile 不具备原子性。想要变量在多线程中具备原子性,可以使用AtomicInteger
    private static volatile int count;
    private static AtomicInteger count = new AtomicInteger(0);
    private static void addCount(){
    for (int i = 0; i < 1000; i++) {
    //count++ ;
    count.incrementAndGet();
    }
    System.out.println(count);
    }

    线程间通信wait、notify

    wait、notify 要配合synchronized 使用。wait 是释放锁,notify 是获取锁。
    public static void main(String[] args) {

        final ListAdd2 list2 = new ListAdd2();
        
        // 1 实例化出来一个 lock
        // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用
        //final Object lock = new Object();
        
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //synchronized (lock) {
                        for(int i = 0; i <10; i++){
                            list2.add();
                            System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                            Thread.sleep(500);
                            if(list2.size() == 5){
                                System.out.println("已经发出通知..");
                                countDownLatch.countDown();
                                //lock.notify();
                            }
                        }                       
                    //}
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            }
        }, "t1");
        
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                //synchronized (lock) {
                    if(list2.size() != 5){
                        try {
                            //System.out.println("t2进入...");
                            //lock.wait();
                            countDownLatch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
                    throw new RuntimeException();
                //}
            }
        }, "t2");   
        
        t2.start();
        t1.start();
        
    }
    

    ThreadLocal

    ThreadLocal 为了解决多线程下变量的问题,一般并发量不是很高的情况下,用synchronized性能比较好,如果是并发特别高的情况下

    相关文章

      网友评论

          本文标题:synchronized 、volatile 、线程通信基础、T

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