java基础----多线程04----线程安全问题

1 产生的原因:当某个线程在执行的过程中,尚未结束操作,其他线程参与进来。

2. 解决:当一个线程操作共享数据的时候,其他线程不能参与进来。

3.解决办法:

       方法一:同步代码块。

                synchronized (同步监视器){

                     //需要被同步的代码

                 }

class SubThread implements Runnable {
	private int ticket = 100;
    Object obj = new Object();
	@Override
	public void run() {
		while (true) {
           synchronized (this) {
        	   if (ticket > 0) {
        		   try {
        			   Thread.currentThread().sleep(100);
        		   } catch (InterruptedException e) {
        			   e.printStackTrace();
        		   }
        		   System.out.println(Thread.currentThread().getName() +"的票号为" + ticket);
        		   ticket--;
        	   } else {
        		   break;
        	   }
	    	}
		}
	}
}

public static void main(String[] args) {

		SubThread s1 = new SubThread();

		Thread t1 = new Thread(s1);
		Thread t2 = new Thread(s1);
		Thread t3 = new Thread(s1);

		t1.setName("窗口一");
		t2.setName("窗口二");
		t3.setName("窗口三");

		t1.start();
		t2.start();
		t3.start();
	}

             注意:①操作共享数据的代码,即为需要被同步的代码

                        ②同步监视器,即:锁。任何一个类的随对象都可以作为锁。

                             要求:多个线程必须公用一把锁。所以需要注意声名的位置。

                             补充:在对于实现Runnable创建的多线程中,可以考虑使用this来作为同步监视器。

                                       在对于继承Thread类来创建的而多线程中,慎用this作为同步监视器。

                        ③注意使用synchronized的方式去同步包装同步代码块的时候,对于解决实现Runnable接口来创建的多线程

                           和继承Threaad类来创建多线程时候,对于共享数据的处理不一样。最主要的是判断锁是不是同一把。

 

        方法二:同步方法。

                     1.同步方法任然涉及到同步监视器,只是不需要显示的申明。

                      2.非静态的同步方法,同步监视器是:this

                          静态的同步方法的同步监视器:当前类本身。

/**
 *使用同步方法来解决实现Runnable接口的创建的多线程的安全问题。
 *
 */
public class Test1 {
	public static void main(String[] args) {

		SubThread s1 = new SubThread();

		Thread t1 = new Thread(s1);
		Thread t2 = new Thread(s1);
		Thread t3 = new Thread(s1);

		t1.setName("窗口一");
		t2.setName("窗口二");
		t3.setName("窗口三");

		t1.start();
		t2.start();
		t3.start();
	}
}

class SubThread1 implements Runnable {
	private int ticket = 100;
	@Override
	public void run() {
		while (true) {
        	   show();
	    	}
	}
	private synchronized void show() {
		if (ticket > 0) {
			   try {
				   Thread.currentThread().sleep(100);
			   } catch (InterruptedException e) {
				   e.printStackTrace();
			   }
			   System.out.println(Thread.currentThread().getName() +"的票号为" + ticket);
			   ticket--;
		   }
	}
}
/**
 *使用同步方法来解决继承Thread创建的多线程的安全问题。
 *
 */
public class Test2 {
	public static void main(String[] args) {

		SubThread2 s1 = new SubThread2();
		SubThread2 s2 = new SubThread2();
		SubThread2 s3 = new SubThread2();


		s1.setName("窗口一");
		s2.setName("窗口二");
		s3.setName("窗口三");

		s1.start();
		s2.start();
		s3.start();
	}
}

class SubThread2 extends Thread {
	private static int  ticket = 100;

	@Override
	public void run() {
		while (true) {
        	   show();
		}
	}

	private static synchronized void show() {//同步监视器:SubThread2.class
		//private  synchronized void show() {//此时默认的锁时调用该方法的线程,因为通过
		                                     //继承Thread的方式创建的多线程,调用的时候
		                                     //每个线程都会调用该方法,所以锁不是唯一的
		if (ticket > 0) {
			   try {
				   Thread.currentThread().sleep(100);
			   } catch (InterruptedException e) {
				   e.printStackTrace();
			   }
			   System.out.println(Thread.currentThread().getName() +"的票号为" + ticket);
			   ticket--;
		   }
	}

 解决线程安全问题方式三:Lock锁

/**
 * 解决线程安全问题方式三:Lock锁
 * 
 * java.util.concurrent.locks.Lock接口是控制对个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问
 *    ,每次只能有一个线程对lock对象加锁,线程在获取共享资源之前要先获得锁对象。
 *    
 *    常用的实现类:ReentrantLock
 * 
 * 1.实例化ReentrantLock
 * 2.调用lock.lock();加锁
 * 3.调用lock.unlock();解锁
 * 
 * 问:synchronized和lock的区别?
 * 同:都可以解决线程的安全问题。
 * 不同:synchronized机制在执行相关的代码同步代码后,自动释放同步监视器。
 *     lock需要手动启动同步,同时结束时也需要手动实现。
 *     
 * 问:如何解决线程安全问题?
 */

class Window implements Runnable {

	private int ticket = 100;
    //1.实例化ReentrantLock
	private ReentrantLock lock = new ReentrantLock();

	@Override
	public void run() {
		while (true) {
			try {
				//调用lock.lock();加锁
				lock.lock();
				if (ticket > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()
							+ ":票号为 " + ticket);
					ticket--;
				} else {
					break;
				}
			} finally {
				//调用lock.unlock();解锁
				lock.unlock();
			}
		}

	}

}

public class TestLock2 {
	public static void main(String[] args) {
		Window w = new Window();

		Thread t1 = new Thread(w);
		Thread t2 = new Thread(w);
		Thread t3 = new Thread(w);

		t1.setName("窗口一");
		t2.setName("窗口二");
		t3.setName("窗口三");

		t1.start();
		t2.start();
		t3.start();

	}
}

4.同步的方式,解决了线程的安全问题。

  局限性:操作同步代码块的时候,只能有一个线程参与。其他线程等待,相当于一个单线程的过程,效率低。

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的纺织品企业财务管理系统,源码+数据库+毕业论文+视频演示 在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对纺织品企业财务信息管理的提升,也为了对纺织品企业财务信息进行更好的维护,纺织品企业财务管理系统的出现就变得水到渠成不可缺少。通过对纺织品企业财务管理系统的开发,不仅仅可以学以致用,让学到的知识变成成果出现,也强化了知识记忆,扩大了知识储备,是提升自我的一种很好的方法。通过具体的开发,对整个软件开发的过程熟练掌握,不论是前期的设计,还是后续的编码测试,都有了很深刻的认知。 纺织品企业财务管理系统通过MySQL数据库与Spring Boot框架进行开发,纺织品企业财务管理系统能够实现对财务人员,员工,收费信息,支出信息,薪资信息,留言信息,报销信息等信息的管理。 通过纺织品企业财务管理系统对相关信息的处理,让信息处理变的更加的系统,更加的规范,这是一个必然的结果。已经处理好的信息,不管是用来查找,还是分析,在效率上都会成倍的提高,让计算机变得更加符合生产需要,变成人们不可缺少的一种信息处理工具,实现了绿色办公,节省社会资源,为环境保护也做了力所能及的贡献。 关键字:纺织品企业财务管理系统,薪资信息,报销信息;SpringBoot
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值