线程安全问题出现的原因和解决方法

                         线程安全问题出现的原因和解决方法

线程安全问题出现的根本原因:

    1. 必须要存在两个或者两个以上的线程共享着一个资源。

    2. 操作共享资源的代码必须有两句或者两句以上。

线程安全问题的解决方案(2个):

解决思路:

就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程是不可以参与运算的。

必需要当前线程把这些带那都执行完毕后,其他线程才能参与运算。

同步的好处:解决了线程的安全问题。

同步的弊端:相对降低了效率,因为同步外的线程都会判断同步锁。

同步的前提:同步中必须有多个线程并使用同一个锁。

    1. 同步代码块

        synchronized(锁){

            需要被同步的代码

        }

class SaleTicket extends Thread{
	 static int num = 50;//票数  非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。
	 public SaleTicket(String name) {
		super(name);
	}
	
	@Override
	public void run() {
		while(true){
			//同步代码块
			synchronized ("锁") {				
				if(num>0){
					System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					num--;
				}else{
					System.out.println("售罄了..");
					break;
				}
			}			
		}
	}			
} 
public class Demo4 {	
	public static void main(String[] args) {
		//创建三个线程对象,模拟三个窗口
		SaleTicket thread1 = new SaleTicket("窗口1");
		SaleTicket thread2 = new SaleTicket("窗口2");
		SaleTicket thread3 = new SaleTicket("窗口3");
		//开启线程售票
		thread1.start();
		thread2.start();
		thread3.start();		
	}	
}

同步代码块需要注意的事项注意:

1. 同步代码块的锁可以是任意的对象。 同步函数的锁是固定的,非静态函数的锁对象是this对象。 静态函数的锁对象是class对象。

2. 锁对象必须是多线程共享的对象,否则锁不住。

3. 在同步代码块或者是同步函数中调用sleep方法是不会释放锁对象的,如果是调用了wait方法是会释放锁对象的。

    2. 同步函数。 

        修饰符 synchronized 返回值类型   函数名(形参列表..){

        }

class BankThread extends Thread{
	static int count = 5000;
	public BankThread(String name){
		super(name);
	}
	
	@Override  //
	public synchronized  void run() {
		while(true){
			synchronized ("锁") {				
				if(count>0){
					System.out.println(Thread.currentThread().getName()+"取走了1000块,还剩余"+(count-1000)+"元");
					count= count - 1000;
				}else{
					System.out.println("取光了...");
					break;
				}
			}
		}
	}
 
public class Demo1 {
 
	public static void main(String[] args) {
		//创建两个线程对象
		BankThread thread1 = new BankThread("老公");
		BankThread thread2 = new BankThread("老婆");
		//调用start方法开启线程取钱
		thread1.start();
		thread2.start();	
	}
	
}

同步函数注意事项:

1.如果函数是一个非静态的同步函数,那么锁对象是this对象;

2.如果函数是静态的同步函数,那么锁对象是当前函数所属的类的字节码文件(class对象);

3.同步函数的锁对象是固定的,不能由自己指定。

 同步函数和同步代码块的区别:

同步函数的锁是固定的this;

同步代码块的锁是任意的对象。

建议使用同步代码块。

静态的同步函数使用的锁是该函数所属字节码文件对象

可以用getClass()方法来获取,也可以用当前 类名.class表示

 

 

全部评论

相关推荐

10-23 16:33
门头沟学院 Java
本人某中9本科,成绩中等,目前没科研没实习,目前后端学到了javaWeb,开始没定好方向,在学国外课程,走工程路线起步有点晚了,到这个时间点了还在学JavaWeb,顿感迷茫,不知道是坚持走下去还是寒假去准备考研。考研这个路弄得我还是心痒痒的,因为从众考研的人也不在少数,所以会有这方面的心理安慰吧,就是“不行我可以去考研啊”,而且意味着三年的缓冲,为了复试还有积攒经验美化简历,其实现在也可以去申入实验室打杂;就业可能意味着多些工作经验,工程岗应该到后面还是经验大于学历?还是有点迷茫了,求助好心人有无路线启发
千千倩倩:同27给点建议,现在这个时间点可以快速看完外卖和点评,不用跟着敲,但一定要在看的时候总结每个部分的整个业务流程,对其中的实现有一个大概的印象。然后直接开始看八股,刷算法。八股和算法最好还是在项目学习中穿插着看。如果计算机基础,算法这些基础好,加上每天刻苦学习,两周可以达到勉强能面试的水平,到时候就直接海投中小厂,在约面和面试的过程中不断巩固知识。没找到实习也没关系,就当积累经验。再沉淀一波直接明年三月开始投暑期,毕竟是9本,总是有面试机会的,只要你这三个月不懈怠,面试发挥得一定不错,只要拿到一个中,大厂暑期实习,秋招就有竞争力了。总得而言,现在还有机会,但是时间非常紧张,需要你结合自己情况考虑,共勉
你会选择考研还是直接就业
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务