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;

}

原文地址:https://www.cnblogs.com/fuckingPangzi/p/10099965.html

时间: 2024-08-30 06:02:27

java的多线程学习,第三记的相关文章

java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:

总结:实现Runnable接口比继承Thread类更有优势: 1.因为java只能单继承,实现Runnable接口可以避免单继承的局限性 2.继承Thread类,多个线程不能处理或者共享同一个资源,但是实现Runnable接口可以处理同一个资源. 下面我们做个测试:验证下.车站的售票系统售票的例子,车站的各个售票口相当于各个线程,我们先使用第一种方法几继承Thread类的方式实现: 代码如下: package com.lp.ecjtu.Thread; /** * * @author Admini

java多线程学习(三)——线程栈

一.线程栈模型 线程栈模型是理解线程调度原理以及线程执行过程的基础.线程栈是指某时刻时内存中线程调度的栈信息,当前调用的方法总是位于栈顶,线程栈的内容是随着线程的运行状态变化而变化的,研究线程栈必须选择一个运行的时刻(指代码运行到什么地方) 上图中的栈A是主线程main的运行栈信息,当执行new JavaThreadDemo().threadMethod();方法时,threadMethod方法位于主线程栈中的栈顶,在threadMethod方法中运行的start()方法新建立了一个线程,此时,

多线程学习(三)Java ThreadLocal

Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量.因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量. 如何创建ThreadLocal变量 以下代码展示了如何创建一个ThreadLocal变量: 1 private ThreadLocal myThreadLocal = new ThreadLocal(); 我们可以看到,通过这段代码实例化了一个ThreadLocal对象.我们只需要

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() { Threa

黑马程序员------Java中多线程学习总结(二)

Java培训.Android培训.iOS培训..Net培训,期待您的交流 在Java多线程中,如果有多个线程同时操作共享数据时,就可能会发生数据异常 如下面这段代码: /* * 模拟卖票 */ class Ticket implements Runnable { private int tick = 10; Object obj = new Object(); public void run() { while(true) { if(tick>0) { try{Thread.sleep(10);

黑马程序员------Java中多线程学习总结(一)

Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! 一.多线程的概念 进程:是一种“自包容”的运行程序,有自己的地址空间. 基于进程的特点是允许计算机同时运行两个或更多的程序 线程:是进程内部单一的一个顺序控制流 . 基于线程的多任务处理环境中,线程是最小的处理单位. 在Java中,一个应用程序可以包含多个线程.每个线程执行特定的任务,并可与其他线程并发执行.多线程使系统的空转时间减少,提高了CPU的利用率.多线程编程隐藏了CPU在任务之间切换的事实. 二.创建

java之jvm学习笔记三(Class文件检验器)

前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,class文件校验器. class文件 校验器,保证class文件内容有正确的内部结构,java虚拟机的class文件检验器在字节码执行之前对文件进行校验,而不是在执行中进行校验 class文件校验器要进行四趟独立的扫描来完成校验工作 class文件校验器分成四趟独立的扫描来完成校验. 第一趟 在装载字节序列的时候进行,这个是校验class文件的结构的合

【Java】多线程学习——wait、notify和notifyAll

Java多线程非常复杂,可以使用BlockingQueue和Executor等工具类来简化使用.但还是要弄清wait().notify()和notifyAll()的作用和用法.它们都是native方法 一.wait() 作用:告诉当前调用它的方法释放锁并sleep,直到其它某个线程也进入sleep状态且调用notify()方法. 注意:该线程在进入waiting之前释放锁,并在wait()方法返回之前重新获取锁.也就是说wait()方法调用之后线程释放锁,然后进入waiting状态. 一直到其它

多线程学习笔记三--------------多线程死锁

多线程死锁: 死锁的常见情形之一:同步的嵌套. public class DeadLock { public static void main(String[] args) throws InterruptedException { Customer cus = new Customer(); Thread t1 = new Thread(cus); Thread t2 = new Thread(cus); t1.start(); Thread.sleep(5); cus.flag = fals