美文网首页
一:多线程之线程安全

一:多线程之线程安全

作者: 一森 | 来源:发表于2019-05-27 22:54 被阅读0次

众所周知进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中肯定包含一个线程(main线程),一个进程中并且可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。

那么什么是线程安全问题?

当N个线程同时操作同一个全局变量或静态变量,做写的操作(修改变量值)时,可能会发生数据冲突问题(资源抢占),也就是线程安全问题。但是做读操作时不会发生数据冲突问题。

举个雷子:

· 创建一个打印方法(打印 当前进程名称&当前耗时任务)


public static void printNum() {
    for (int i =0; i <5; i++) {
        System.out.println("线程名称:" + Thread.currentThread().getName() +" 耗时打印:" + i);
    }
}

·创建两个线程

public static class MyThread1 extends Thread {
        @Override
        public void run() {
            super.run();

            printNum();
        }
}

public static class MyThread2 extends Thread {
        @Override
        public void run() {
            super.run();

            printNum();
        }
}

·在main函数中开启两个线程

public static void main(String[] agrs) {
        MyThread1 myThread1 = new MyThread1();
        myThread1.start();

        MyThread2 myThread2 = new MyThread2();
        myThread2.start();
}

·看下输出

线程名称:Thread-0 耗时打印:0
线程名称:Thread-0 耗时打印:1
线程名称:Thread-0 耗时打印:2
线程名称:Thread-1 耗时打印:0
线程名称:Thread-0 耗时打印:3
线程名称:Thread-1 耗时打印:1
线程名称:Thread-0 耗时打印:4
线程名称:Thread-1 耗时打印:2
线程名称:Thread-1 耗时打印:3
线程名称:Thread-1 耗时打印:4

哎呀我去~交叉打印,我们来看下是为啥子:
原来线程的执行是CPU随机执行的,比如我们开启N个线程,这N个线程并不是同时执行的,而是CPU快速的在这N个线程之间切换执行,所以才会出现上面的情况,那么我们如何来解决这个问题呢?

在JDK1.5之前是通过关键字 synchronized 来进行代码同步的,也就是说当线程A执行该方法时就宣布了现在这个代码是我的了,如果 此时线程B想来执行这段代码,线程A说没门,让我干完再说;

·将printNum方法增加synchronized关键字

public static synchronized void printNum() {
        for (int i = 0; i < 5; i++) {
            System.out.println("线程名称:" + Thread.currentThread().getName() + " 耗时打印:" + i);
        }
}

·看效果

线程名称:Thread-0 耗时打印:0
线程名称:Thread-0 耗时打印:1
线程名称:Thread-0 耗时打印:2
线程名称:Thread-0 耗时打印:3
线程名称:Thread-0 耗时打印:4
线程名称:Thread-1 耗时打印:0
线程名称:Thread-1 耗时打印:1
线程名称:Thread-1 耗时打印:2
线程名称:Thread-1 耗时打印:3
线程名称:Thread-1 耗时打印:4

在JDK1.5之后java加了个Lock锁,也是解决这个问题的,如果说synchronized是隐式的,那么Lock就是显示的,需要开发者进行上锁及解锁操作

看骚操作:

static Lock lock = new ReentrantLock();

public static void printNum() {
        lock.lock();
        try {
            for (int i = 0; i < 5; i++) {
                System.out.println("线程名称:" + Thread.currentThread().getName() + " 耗时打印:" + i);
            }
        } finally {
            lock.unlock();
        }
}

首先通过ReentrantLock创建了一个Lock,在代码前加上Lock.lock方法,那么unlock要放在finally中呢,原因是假如线程A执行代码出现异常unlock可能就不能被执行,也就是无法进行解锁,那么线程B就无法拿到锁,就无法进行代码执行了

看效果:

线程名称:Thread-0 耗时打印:0
线程名称:Thread-0 耗时打印:1
线程名称:Thread-0 耗时打印:2
线程名称:Thread-0 耗时打印:3
线程名称:Thread-0 耗时打印:4
线程名称:Thread-1 耗时打印:0
线程名称:Thread-1 耗时打印:1
线程名称:Thread-1 耗时打印:2
线程名称:Thread-1 耗时打印:3
线程名称:Thread-1 耗时打印:4

两种线程同步(抢占资源)的解决方式:

1、方法或代码块增加synchronized 关键字
2、方法前lock 方法后 unlock

相关文章

  • iOS关于property中的atomic和nonatomic

    首先这两个属性特质是为了处理多线程安全问题,那么什么是多线程安全,多线程安全就是多个线程访问同一段代码、指针区域、...

  • Android 多线程探索(四)— 同步集合

    前言 Android JDK 提供了一系列线程安全的集合,避免多线程环境下由于线程安全导致的各种问题。 一、程序之...

  • 多线程基础之常见概念的理解

    多线程基础之常见概念的理解 我这里从线程的关键概念入手,介绍一下多线程,并且结合代码说下自己的理解。 线程安全 我...

  • 多线程之线程安全性

    多线程环境下使用非线程安全类会导致线程安全问题。线程安全问题表现为原子性,有序性,可见性 在讲述线程安全三大特性之...

  • 线程安全知多少

    1. 如何定义线程安全 线程安全,拆开来看: 线程:指多线程的应用场景下。 安全:指数据安全。 多线程就不用过多介...

  • 2018-05-08

    多线程 初级概念与传参 join deatch 原子变量 互斥锁 与 线程安全 线程安全 多线程访问冲突 冲突...

  • 后端架构师技术图谱(三)-并发、锁、设计模式(二)

    并发 多线程 《40个Java多线程问题总结》 线程安全 《Java并发编程——线程安全及解决机制简介》 一致性、...

  • ConcurrentHashMap

    总结 HashMap在多线程中不安全,java提供了线程安全的ConcurrentHashMap 类,保证在多线程...

  • HashMap相关

    HashMap是数组+链表 1.HashMap不是线程安全,为什么不是线程安全的呢? 多线程put,多线程reha...

  • 几个小问题

    1、FMDB与多线程 SQLITE默认的线程模式是串行模式, 是线程安全的FMDatabase多线程不安全, 单个...

网友评论

      本文标题:一:多线程之线程安全

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