欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

线程安全

程序员文章站 2022-05-14 10:21:35
1. 什么叫线程安全? 多线程对共享资源进行写的操作,受到其他线程的干扰,导致数据偶问题,这种现象叫做线程安全问题。 运行结果: 线程安全解决的办法: 使用多线程之间同步synchronized或使用锁(lock)。 为什么使用线程同步或使用锁能解决线程安全问题呢? 将可能发生线程安全的代码,在同一 ......

1. 什么叫线程安全?

    多线程对共享资源进行的操作,受到其他线程的干扰,导致数据偶问题,这种现象叫做线程安全问题。

package com.cn.test.thread;

public class trainthread implements runnable {

    /**
     * 两个线程进行售票100张
     */
    private  int trainticket = 100;
    @override
    public void run() {
        
        while (trainticket > 0) {
            try {
                thread.sleep(10);
            } catch (interruptedexception e) {
                e.printstacktrace();
            }
            // 进行售票
            system.out.println(thread.currentthread().getname() + "开始售票:" + (100 - trainticket + 1) + "张");
            trainticket--;
        }
    }

    public static void main(string[] args) {
        trainthread train = new trainthread();
        thread  t1 = new thread(train,"窗口1");
        thread  t2 = new thread(train,"窗口2");
        t1.start();
        t2.start();
    }
}

运行结果:

窗口1开始售票:1张
窗口2开始售票:1张
窗口1开始售票:3张
窗口2开始售票:3张
窗口1开始售票:5张
窗口2开始售票:5张
窗口1开始售票:7张
窗口2开始售票:7张
窗口2开始售票:9张
窗口1开始售票:9张
窗口2开始售票:11张
窗口1开始售票:12张
窗口2开始售票:13张
窗口1开始售票:14张
窗口2开始售票:15张
窗口1开始售票:16张
窗口2开始售票:17张
窗口1开始售票:18张
窗口2开始售票:19张
窗口1开始售票:20张
窗口2开始售票:21张
窗口1开始售票:22张
窗口2开始售票:23张
窗口1开始售票:24张
窗口2开始售票:25张
窗口1开始售票:26张
窗口2开始售票:27张
窗口1开始售票:28张
窗口2开始售票:29张
窗口1开始售票:30张
窗口2开始售票:31张
窗口1开始售票:32张
窗口2开始售票:33张
窗口1开始售票:34张
窗口2开始售票:35张
窗口1开始售票:36张
窗口2开始售票:37张
窗口1开始售票:38张
窗口2开始售票:39张
窗口1开始售票:40张
窗口2开始售票:41张
窗口1开始售票:42张
窗口2开始售票:43张
窗口1开始售票:44张
窗口2开始售票:45张
窗口1开始售票:46张
窗口2开始售票:47张
窗口1开始售票:48张
窗口2开始售票:49张
窗口1开始售票:50张
窗口2开始售票:51张
窗口1开始售票:52张
窗口2开始售票:53张
窗口1开始售票:54张
窗口2开始售票:55张
窗口1开始售票:56张
窗口2开始售票:57张
窗口1开始售票:58张
窗口2开始售票:59张
窗口1开始售票:60张
窗口2开始售票:61张
窗口1开始售票:62张
窗口2开始售票:63张
窗口1开始售票:64张
窗口2开始售票:65张
窗口1开始售票:66张
窗口2开始售票:67张
窗口1开始售票:68张
窗口2开始售票:69张
窗口1开始售票:70张
窗口2开始售票:71张
窗口1开始售票:72张
窗口2开始售票:73张
窗口1开始售票:74张
窗口2开始售票:75张
窗口1开始售票:76张
窗口2开始售票:77张
窗口1开始售票:78张
窗口2开始售票:79张
窗口1开始售票:80张
窗口2开始售票:81张
窗口1开始售票:82张
窗口2开始售票:83张
窗口1开始售票:84张
窗口2开始售票:85张
窗口1开始售票:86张
窗口2开始售票:87张
窗口1开始售票:88张
窗口2开始售票:89张
窗口1开始售票:90张
窗口2开始售票:91张
窗口1开始售票:92张
窗口2开始售票:93张
窗口1开始售票:94张
窗口2开始售票:95张
窗口1开始售票:96张
窗口2开始售票:97张
窗口1开始售票:98张
窗口2开始售票:99张
窗口1开始售票:100张
窗口2开始售票:101张

线程安全解决的办法:

        使用多线程之间同步synchronized或使用锁(lock)。

为什么使用线程同步或使用锁能解决线程安全问题呢?

       将可能发生线程安全的代码,在同一时刻只有一个线程对此进行操作,代码执行完毕之后释放锁之后才让其他线程并发执行,这样就会解决线程安全的问题。

什么是线程同步?

     多个线程共享同一个资源,不会受到其他线程的干扰。

解决办法1:

       同步代码块。 将可能发生线程安全的代码用同步代码块包裹起来。

              synchronized(同一个数据) {

                   可能会发生线程冲突问题

                }

        同步代码块需要传递的对象(锁对象):就是锁住这个对象,表示这个对象正在为我服务,其他人不能用(非synchronized代码块、方法除外)。

 

		
		while (trainticket > 0) {
			try {
				thread.sleep(50);
			} catch (interruptedexception e) {
				e.printstacktrace();
			}
			synchronized (obj) {
				// 进行售票
				if (trainticket > 0) {
					system.out.println(thread.currentthread().getname() + "开始售票:" + (100 - trainticket + 1) + "张");
					trainticket--;
				}
			}
		}
	

  解决办法2:

           同步函数,在发生线程安全的函数中加入sychnorized关键字。

  静态同步函数:

     方法上加上static关键字,使用synchronized 关键字修饰 或者使用类.class文件。静态的同步函数使用的锁是  该函数所属字节码文件对象可以用 getclass方法获取,也可以用当前  类名.class 表示。

死锁:

 

同步中嵌套同步,导致锁无法释放

 

 

package com.cn.test.thread;

public class testdeadthread implements runnable {

    
    
    private boolean flag = true;
    private static int traincount = 100;
    private object mutex = new object();

    @override
    public void run() {
        if (flag) {
            while(true) {
                synchronized (mutex) {
                     sale();
                }
            }
        } else {
            while (true) {
                sale();
            }

        }

    }

    private synchronized void sale() {
        synchronized (mutex) {
            if (traincount > 0) {
                try {
                    thread.sleep(40);
                } catch (exception e) {

                }
                system.out.println(thread.currentthread().getname() + ",出售 第" + (100 - traincount + 1) + "张票.");
                traincount--;
            }
        }
    }

    public static void main(string[] args) throws interruptedexception {
        testdeadthread  test1 = new testdeadthread();
        thread t1 = new thread(test1,"thread-1");
        thread t2 = new thread(test1,"thread-2");
        t1.start();
        thread.sleep(40);
        test1.flag  = false;
        t2.start();


    }

}

 

运行结果:

thread-1,出售 第1张票.
thread-1,出售 第2张票.
thread-1,出售 第3张票.
thread-1,出售 第4张票.
thread-1,出售 第5张票.
thread-1,出售 第6张票.
thread-1,出售 第7张票.
thread-1,出售 第8张票.
thread-1,出售 第9张票.
thread-1,出售 第10张票.
thread-1,出售 第11张票.
thread-1,出售 第12张票.
thread-1,出售 第13张票.
thread-1,出售 第14张票.
thread-1,出售 第15张票.
thread-1,出售 第16张票.
thread-1,出售 第17张票.
thread-1,出售 第18张票.
thread-1,出售 第19张票.
thread-1,出售 第20张票.
thread-1,出售 第21张票.
thread-1,出售 第22张票.
thread-1,出售 第23张票.
thread-1,出售 第24张票.
thread-1,出售 第25张票.