并发编程之线程安全

为什么会有线程安全问题?

当多个线程同时共享一个全局变量或静态变量时,在做写的操作时,可能回发生线程冲突问题,也就是线程安全问题。(读的时候不会发生数据冲突问题);

解决方法: 

  1. 使用多线程之间同步(内置锁[synchronized])或Lock锁;
  2. 使用锁的话,只能让一个线程执行执行,代码执行完成之后释放锁,然后才让其他线程进行执行,这样的话就可以解决线程不安全的问题;
  3. 同步:当多个线程共享一个资源时,不会受到其他线程的干扰;
package com.train;

class TrainThreads implements Runnable {

	// 火车票票数
	private int count = 10;

	@Override
	public void run() {
		while (count > 0) { // 小于0 线程就会结束
			try {
				Thread.sleep(50);
			} catch (Exception e) {
				e.printStackTrace();
			}
			sale();
		}
	}

	/* 使用 synchronized 内置锁
	 * public synchronized void sale() {
		if (count > 0) {
			// 100 张火车票 - 当前火车票数 + 1   Thread.currentThread().getName() 获取线程名称
			System.out.println(Thread.currentThread().getName() + " 出售 " + ((10 - count) + 1) + " 火车票 ");
			count--;
		}
	}*/

	public  void sale() {
		if (count > 0) {
			// 100 张火车票 - 当前火车票数 + 1   Thread.currentThread().getName() 获取线程名称
			System.out.println(Thread.currentThread().getName() + " 出售 " + ((10 - count) + 1) + " 火车票 ");
			count--;
		}
	}
	
}

public class Test {
	
	public static void main(String[] args) {
		
		TrainThreads trainThread = new TrainThreads();
		//创建线程1
		Thread t1 = new Thread(trainThread,"窗口1");
		//创建线程2
		Thread t2 = new Thread(trainThread,"窗口2");
		
		t1.start();
		t2.start();
	}

}

 不加鎖执行结果:

 

package com.train;

class TrainThreads implements Runnable {

	// 火车票票数
	private int count = 10;

	@Override
	public void run() {
		while (count > 0) { // 小于0 线程就会结束
			try {
				Thread.sleep(50);
			} catch (Exception e) {
				e.printStackTrace();
			}
			sale();
		}
	}

	 //使用 synchronized 内置锁 (同步方法)
	 public synchronized void sale() {
		if (count > 0) {
			// 100 张火车票 - 当前火车票数 + 1   Thread.currentThread().getName() 获取线程名称
			System.out.println(Thread.currentThread().getName() + " 出售 " + ((10 - count) + 1) + " 火车票 ");
			count--;
		}
	}

	/*public  void sale() {
		if (count > 0) {
			// 100 张火车票 - 当前火车票数 + 1   Thread.currentThread().getName() 获取线程名称
			System.out.println(Thread.currentThread().getName() + " 出售 " + ((10 - count) + 1) + " 火车票 ");
			count--;
		}
	}*/
	
}

public class Test {
	
	public static void main(String[] args) {
		
		TrainThreads trainThread = new TrainThreads();
		//创建线程1
		Thread t1 = new Thread(trainThread,"窗口1");
		//创建线程2
		Thread t2 = new Thread(trainThread,"窗口2");
		
		t1.start();
		t2.start();
	}

}

加锁执行结果:

 

 注意:使用内置锁(sunchronized)。保证线程原子性,当线程进入方法的时候,自动获取锁,一旦锁被其他线程获取到后,其他线程就会等待。 
              特征:只有一个线程进行使用。程序执行完毕之后,会自动释放锁。
              注意:加上内置锁,只能提高性能安全性,但是会降低程序的运行效率。 当锁被占用时,其他线程需要等待,这个时候就进入了休眠状态。当它获取锁的时候,会进行资源切换。资源的竞争。  
              内置锁也是重入锁,锁可以重复传递,重复使用。
              内置锁也是互斥锁,A线程拿到锁,B线程必须等A线程释放锁之后才能获取资源。
使用方式:同步方法,同步代码块。

线程的三大特性:

          原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 

          可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 

          有序性:程序执行的顺序按照代码的先后顺序执行。 

什么是多线程死锁?

同步中嵌套同步,导致锁的资源无法释放。

ThreadLocal 和 Volatile 的用法?

ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。(也就是说 ThreadLocal 为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量)。

Volatile 使用Volatile修饰的变量一旦被某个线程修改,修改的值会立刻被更新的主内存中,当其他线程需要读取时,可以立刻获取到修改后的值。

Java内存模型?

Java内存模型简称jmm,定义了一个线程对另一个线程可见。共享变量存放在主内存中,每个线程都有自己的本地内存,当多个线程同时访问一个数据的时候,可能本地内存没有及时刷新到主内存,所以就会发生线程安全问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值