java的多线程学习,第三记

一,Java内存模型

Java内存模型规定了所有的内存变量都存储在主内存中。每条线程中还有自己的工作内存,线程的工作内存中保存了被该线程所使用到的变量(这些变量是从主内存中拷贝而来)。线程对变量的所有操作(读取,赋值)都必须在工作内存中进行。不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均通过主内存来完成

基于这种模型的多线程就会出现很多问题,多线程的---------脏读数据

举例说明:

i=123++;

现在有同时2个线程执行这段代码,加入初始值为123,那么有两个线程正常情况下得到的值,正常的值是125,

但是呢,初始时,两个线程分别读取i的值存入到各自所在的工作内存中,然后线程1进行加1操作,然后把i的最新值124写入到内存。此时线程2的工作内存当中的i的值还是123,进行加1操作,i的值还是为124,然后线程2把i的值写入内存。

最终结果i的值是124,而不是125.这就是-----------------缓存一致性的问题。这种被多个线程访问的变量为共享变量。

volatile 保证了变量的修改让所有的线程可见  阻止指令排序  相对的来说

volatile 当一个共享变量被volatile修饰的时候呢,它会保证修改的值会立即被更新到内存,当有其他线程需要读取时,它会去内存中读取新值。

sync 能够解决 可见性 原子性  volatile只能解决可见性  if()操作

例如,当第一个线程比较之后,进来修改了值,第二个比较之后,拿到的值还是原来的值,变量没有原子化

大多数多线程问题都是由CAS操作引起的。compare and set 先比较,后修改。

如何解决多线程问题呢:

1,线程封闭:final 不要线程之间共享变量

2,堆栈 栈封闭 比如 方法内部声明 修改  这样不会溢出

3,ThreadLocal 线程绑定

 Synchronized用于线程之间的数据共享(使变量或者代码块在某一时刻只能被一个线程访问),是一种以延长访问时间来换取线程安全性的策略。

ThreadLocal则用于线程之间的数据隔离(为每一个线程都提供了变量的副本),是一种以空间来换取线程安全性的策略.

ThreadLocal的使用:

package fiveSteps;

/**
 * @author liugang
 * @create 2018/12/10 23:53
 **/
public class MainLocalTest {

    private static ThreadLocal<LocalTest> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        LocalTest local = new LocalTest();

        new Thread(){
            @Override
            public void run() {
                for (;;){
                    threadLocal.set(local);
                    LocalTest l = threadLocal.get();
                    l.setNum(20);
                    System.out.println(Thread.currentThread().getName()+"--------------"+threadLocal.get().getNum());
                    Thread.yield();
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                for (;;){
                    threadLocal.set(local);
                    LocalTest l = threadLocal.get();
                    l.setNum(30);
                    System.out.println(Thread.currentThread().getName()+"--------------"+threadLocal.get().getNum());
                    Thread.yield();
                }
            }
        }.start();
    }
}
package fiveSteps;

/**
 * @author liugang
 * @create 2018/12/10 23:51
 **/
public class LocalTest {
    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    private int num;


}

猜你喜欢

转载自www.cnblogs.com/fuckingPangzi/p/10099965.html