【java】【多线程】线程安全与线程非安全【1】

xiaoxiao2021-02-27  498

线程安全与线程非安全,怎样区分呢?

其实,当线程访问同一资源时,如同一个对象的同一个变量,会存在多个线程对同一资源的竞争访问,也就存在线程非安全。所以说,非安全指的是:多个线程访问同一个资源,可能会访问到非想要的资源。如线程一改写了变量a,而线程二此时又来访问变量a,则线程二得到的是修改后的变量a,而不是修改前的变量a。这样,就存在了数据的非安全访问,称之为线程非安全。这也可以称为数据的脏读。

反之,如果两个线程不会访问同样的资源,则不会存在上述问题,所以,称之为线程安全。

那是不是只要;两个线程访问同一对象的同一资源就是线程不安全的呢?

这也不是。如果访问的是同一个方法,而该方法有没有访问类的其他属性,则该方法的访问不存在线程安全问题。即:方法内部的局部变量是线程安全的。

代码如下:

package com.cmm.thread1; public class ThreadSafe { public void add(int a) throws InterruptedException{ int num = 0; if(a == 100){ num = 100; Thread.sleep(1000); System.out.println("num = " + num); }else{ num = 200; System.out.println("num = " + num); } } } package com.cmm.thread1; public class ThreadA extends Thread{ private ThreadSafe safe; public ThreadA(ThreadSafe safe) { this.safe = safe; } @Override public void run() { super.run(); try { this.safe.add(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } package com.cmm.thread1; public class ThreadB extends Thread{ private ThreadSafe safe; public ThreadB(ThreadSafe safe) { this.safe = safe; } @Override public void run() { super.run(); try { this.safe.add(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 测试代码如下:

package com.cmm.thread1; public class Main { public static void main(String[] args) { ThreadSafe safe = new ThreadSafe(); ThreadA threadA = new ThreadA(safe); ThreadB threadB = new ThreadB(safe); threadA.start(); threadB.start(); } } 多次测试结果为:

num = 200 num = 100

可以看出,多个线程访问同一方法的局部变量是线程安全的。

但是,如果是类的属性,则存在线程不安全的问题。

修改代码如下:

package com.cmm.thread1; public class ThreadSafe { private int num = 0; public void add(int a) throws InterruptedException{ if(a == 100){ num = 100; Thread.sleep(1000); System.out.println("num = " + num); }else{ num = 200; System.out.println("num = " + num); } } } 测试结果如下:

num = 200 num = 200

可以看出,出现的数据脏读。

当多线程访问同一资源时,就会出现脏读问题。所以,这个时候,需要用一定的手段,来使得同一时刻,只有一个线程可以对共享资源进行访问。访问分两种,只读,读写。所以又有不同的处理。

后面,会详细介绍线程同步问题。

在这里先总结一句话:线程同步问题,就是为了解决多个线程对共享数据的同时访问问题,访问又分为只读与读写两种,所以,线程同步,需要分场景做不同的讨论处理。

转载请注明原文地址: https://www.6miu.com/read-485.html

最新回复(0)