java (threading features, Volatile role, java memory model)

1.java thread properties

  1. atomic composition: one or more operations either all operations performed and the execution will not be interrupted by any factor, or to not perform a bank transfer, turn yourself to others 100, others little more than their own account 100 100

  Does not appear, they own less than 100 people there but there is no case more than 100

  2. ordering: the program execution sequence performed in the order code . In general processor in order to improve process efficiency, might enter the code optimization, it does not ensure the implementation of the program in individual statements in the order consistent with the order of the code, but it will ensure that the final program execution and results of the code sequence the result is consistent

  3. Visibility: When multiple threads access the same variables together, one thread modifies the value of the variable, should be able to see the other threads to modify this variable

 

2.java memory model

 java memory model, also known as shared memory model (JMM) java memory model determines the number of threads share the same variables when a thread modifies shared variables, this change should be seen by other threads.

Static int a = 3, for example, when the variable is shared by multiple threads, a = 3 is placed in the main memory, each thread has its own private local memory, private local memory is stored in the shared memory copy of the variable

 Thread variables A, B operating main memory shared variable, will first copy of main memory to the thread A, B own local memory, save a copy. If it is to ensure the visibility of the thread, the thread local memory A copy of modified later, into the main memory needs to be refreshed, then thread after thread B refresh value A is updated again to the main memory.

 

 

0 is the current main memory (the shared variable int a = 0) if there are two threads A, B the value of the main memory operation, A, B thread first main memory copy of the value to its own local memory, If A thread modify variables

a value of 1, the value A modified thread in its own local memory, in which case the value B and the thread in the main memory or 0, when the thread A, B of communication, it will thread A in a local memory variable values ​​flushed to main memory, then thread B

The time required to operate a variable, you will get the latest value of first-main memory, copied to its own local memory

 

3.Volatile保证变量的可见性

 

package com.thread;

class ThreadVolatileDemo extends Thread {
    public boolean flag = true;

    @Override
    public void run() {
        System.out.println("开始执行子线程....");
        while (flag) {

        }
        System.out.println("线程停止");
    }

    public void setRuning(boolean flag) {
        this.flag = flag;

    }

}

public class VolatileDemo {
    public static void main(String[] args) throws InterruptedException {
        ThreadVolatileDemo threadVolatileDemo = new ThreadVolatileDemo();
        threadVolatileDemo.start();
        Thread.sleep(3000);
        threadVolatileDemo.setRuning(false);
        System.out.println("理想状况下设置false以后线程会停止运行");
        Thread.sleep(1000);
        System.out.println(threadVolatileDemo.flag);

    }
}

 

 

 

 输出结果

开始执行子线程....
理想状况下设置false以后线程会停止运行
false
(一直执行while循环,已经将flag设置成了false 但是程序一直没有停止,是因为 该线程一直读取的是副本,并没有去刷新主内存中的值)

 

 


Volatile关键字将解决线程之间可见性, 强制线程每次读取该值的时候都去“主内存”中取值

 

  用法:public boolean volatile flag;

   每个线程操作flag的时候,都会去主内存刷新最新的flag值

 

4.Volatile是否能保证线程的安全性(原子性)

 

package com.thread;

public class VolatileSyn extends Thread {
    public static volatile int count = 0;

    public void run() {
        for (int i = 0; i < 1000; i++) {
            count++;

        }

    }

    public static void main(String[] args) throws InterruptedException {
        VolatileSyn[] volatileSyns = new VolatileSyn[4];
        for (int i = 0; i < volatileSyns.length; i++) {
            volatileSyns[i] = new VolatileSyn();
        }
        for (VolatileSyn volatileSyn : volatileSyns) {
            volatileSyn.start();
        }
        Thread.sleep(4000);
        System.out.println(VolatileSyn.count);
    }

}

 

 

  创建4条线程或者10条线程,共享可见变量count,每个线程都执行+1000的操作,理论值应该是4000,但是多次执行的结果 ,count++是线程不安全

最后的值 不等于4000(也有等于4000的) 多次操作结果不同 由此可见volatile并不能保证线程的安全问题。volatile能保证线程的可见性,例如:A 线程刚从主内存刷新过来count值 正准备操作的时候,B线程 修改了count的值 此时A 的值就不是最新的了

 

5.AtomicInteger原子类

AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。

package com.thread;

import java.util.concurrent.atomic.AtomicInteger;

public class VolatileNoAtomic extends Thread {
    private static AtomicInteger count = new AtomicInteger(0);

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            //等同于i++
            count.incrementAndGet();
            //decrementAndGet
        }

    }

    public static void main(String[] args) throws InterruptedException {
        // 初始化10个线程
        VolatileNoAtomic[] volatileNoAtomic = new VolatileNoAtomic[10];
        for (int i = 0; i < 10; i++) {
            // 创建
            volatileNoAtomic[i] = new VolatileNoAtomic();
        }
        for (int i = 0; i < volatileNoAtomic.length; i++) {
            volatileNoAtomic[i].start();
        }
        Thread.sleep(4000);
        System.out.println(VolatileNoAtomic.count);
    }

}

6.volatile与synchronized区别

仅靠volatile不能保证线程的安全性。(原子性)

①volatile轻量级,只能修饰变量。synchronized重量级,还可修饰方法

②volatile只能保证数据的可见性,不能用来同步,因为多个线程并发访问volatile修饰的变量不会阻塞。

synchronized不仅保证可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行。多个线程争抢synchronized锁对象时,会出现阻塞。

线程安全性

线程安全性包括两个方面,①可见性。②原子性。

从上面自增的例子中可以看出:仅仅使用volatile并不能保证线程安全性。而synchronized则可实现线程的安全性。

 

7.wait()、notify、notifyAll()方法

wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。

这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。

 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。

如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。

如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

注意:一定要在线程同步中使用,并且是同一个锁的资源

 

8.wait和sleep的区别

 1.wait是obejct方法,sleep是Thread方法

 2.wait方法调用以后,需要手动唤醒,Sleep休眠 休眠时间到了以后,不需要任何操作能继续向下执行(监控状态依然保持)

 3.wait方法放弃当前线程持有的锁,sleep只是放弃当前cpu的持有,但当前线程还是持有对象锁

 

Guess you like

Origin www.cnblogs.com/920913cheng/p/11364478.html