同步(解决多线程安全问题)

1.创建线程的两种方式。

  (1)继承Thread(该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法也就是说Thread类中的run方法,用于存储线程要运行的代码。)


  
(2)实现Runnable(Runable中只定义了一个抽象方法,public void run();)

    步骤:

    1,定义类实现Runable接口

    2,覆盖Runable接口中的run方法。

    将线程要运行的代码存放在该run方法中。

    3,通过Thread类建立线程对象。

    4,将Runable接口的子类对象作为实际参数传递给Thread类的构造函数。

      为什么要将Runable接口的子类对象传递给Thread类的构造函数。

      因为,自定义run方法所属的对象是Runable接口的子类对象。所以要让线程去指定 指定对象的run方法。就必须明确该run方法所属的对象。

    5,调用Thread类的start方法开启线程并调用Runable接口的子类的run方法。

      在Thread类中提供了public Thread(Runnable target)和public Thread(Runnable target,String name)两种构造方法


    两种方式的区别?

    继承Thread:线程代码存放在Thread子类run方法中

    实现Runable:线程代码存在接口的子类的run方法。

    Thread类也是Runnable的子类。也就是说,Thread和Runnable的子类都同时实现了Runnable接口,之后将Runnable的子类实例放到了Thread类之中。

    Thread类和Runnable接口使用上的区别,如果一个类继承Thread类,则不适合于多个线程共享资源,而实现了Runnable接口,就可以方便地实现资源的共享。

2.多线程的运行出现了安全问题。

问题的原因:

当多条语句在操作同一个线程共享数据时,一个线程对多条语句执行了一部分,还没执行完,另一线程参与进来执行。导致共享数据的错误。

解决办法:

对多条操作共享数据的语句,只能让一个线程都执行完,再执行过程中,其他线程不可以参与运行。

java对于多线程的安全问题,提供了专业的解决方式,就是同步代码块。

同步代码块格式:

  synchronized(对象1){

      需要同步的代码

    }

这个里面的对象1就如同锁,持有锁的线程,可以在同步中执行需要同步的代码。

没有持有锁的线程即使获得CPU的执行权,也进不去,因为没有获取锁。

同步的前提:

(1)必须要有两个或两个以上的线程。

(2)必须有多个线程并使用同一个锁。

必须保证同步中只能有一个线程在运行。

同步的好处和弊端:

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

弊端:同步外的多个线程都需要判断锁,(这些是无效判断)较为消耗资源。

package org.lxh.demo9.threaddemo;
class Ticket implements Runnable{
    private  int tick=5;
    public void run(){
        while (true){
            synchronized(this){  //this是一个锁。
                if (tick>0){
                try{
                    Thread.sleep(500);
                }
                catch(Exception e){

                }
                System.out.println(Thread.currentThread().getName()+"sale..."+tick--);
            }
        }
            }

} 

public class TicketDemo {

    public static void main(String[] args) {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);//创建了一个线程
        Thread t2=new Thread(t);//创建了一个线程
        Thread t3=new Thread(t);//创建了一个线程
        t1.start();
        t2.start();
        t3.start();
    }

} 

3.死锁

 常见情景之一:同步的嵌套

class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag = flag;
	}

	public void run()
	{

		if(flag)
		{
			while(true)
				synchronized(MyLock.locka)
				{
					System.out.println(Thread.currentThread().getName()+"..if   locka....");
					synchronized(MyLock.lockb)				{

						System.out.println(Thread.currentThread().getName()+"..if   lockb....");
					}
				}
		}
		else
		{
			while(true)
				synchronized(MyLock.lockb)
				{
					System.out.println(Thread.currentThread().getName()+"..else  lockb....");
					synchronized(MyLock.locka)
					{
						System.out.println(Thread.currentThread().getName()+"..else   locka....");
					}
				}
		}

	}

}

class MyLock
{
	public static final Object locka = new Object();
	public static final Object lockb = new Object();
}

class DeadLockTest
{
	public static void main(String[] args)
	{
		Test a = new Test(true);
		Test b = new Test(false);

		Thread t1 = new Thread(a);
		Thread t2 = new Thread(b);
		t1.start();
		t2.start();
	}
}

  运行结果:Thread1..else lockb...

       Thread0..if locka...

可以看到线程1拿到了lockb锁,而线程0拿到了locka锁,之后就发生了死锁,因为线程1拿到lockb锁之后,还要想往下运行,需要拿到locka锁,而locka锁在线程0那里;线程0拿到locka锁,想往下执行,需要拿到locka锁,但是lockb锁在线程1那里。这样就形成了死锁。

时间: 2024-12-20 04:50:56

同步(解决多线程安全问题)的相关文章

如何用SingleThreadModel解决多线程安全问题

2.用SingleThreadModel解决多线程安全问题:(视频下载) (全部书籍) 前 面介绍的都是普通的Servlet.对于每一个用户请求,那些Servlet都会用线程的方式给予应答.这样比较节省系统的资源.Sun公司也给出了另外 一种方法,就是这节要介绍的SingleThreadModel的方法.当implement这个接口以后,你的Servlet就变成了另外一种模式工 作.即,每一个新用户的请求,都会生成一个新的Servlet实例来应答.这种方法有两个方面的弊病.一是性能太差,最后会把

java 22 - 12 多线程之解决线程安全问题的实现方式1

从上一章知道了多线程存在着线程安全问题,那么,如何解决线程安全问题呢? 导致出现问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 上一章的程序,上面那3条都具备,所以肯定出问题. 如何解决问题: 原因A.B肯定不能改变,所以只能改变原因C 解决问题思路: 如果把多条语句操作共享数据的代码给包成一个整体,让某个线程在执行这个整体的时候,别的线程不能执行. 这时候就用到了java提供的:同步机制 同步代码块: synchronized(对象){  需要同步的代码

java基础知识回顾之java Thread类学习(五)--java多线程安全问题(锁)同步的前提

这里举个例子讲解,同步synchronized在什么地方加,以及同步的前提: * 1.必须要有两个以上的线程,才需要同步. * 2.必须是多个线程使用同一个锁. * 3.必须保证同步中只能有一个线程在运行,锁加在哪一块代码 那么我们要思考的地方有:1.知道我们写的哪些是多线程代码 2.明确共享数据 3.明确多线程运行的代码中哪些语句是操作共享数据的.. 4.要确保使用同一个锁. 下面的代码:需求:两个存户分别往银行存钱,每次村100块,分三次存完. class bank{ private int

Java Tread多线程(2)多线程安全问题

作者 :卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39348093 本文演示,Tread多线程安全问题,以及一种解决多线程安全方式(线程同步). 1)一个线程不安全的Demo 2)线程同步 一.小Demo演示引出线程安全问题: package thread.runable1.qdj; //1.定义类实现Runnable接口 class RunDemo1 implements Runnable { private int x =

Spring学习11- Spring使用ThreadLocal解决线程安全问题

ThreadLocal是什么      早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”.其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些.      当使用ThreadLoca

java基础知识回顾之java Thread类学习(四)--java多线程安全问题(锁)

上一节售票系统中我们发现,打印出了错票,0,-1,出现了多线程安全问题.我们分析为什么会发生多线程安全问题? 看下面线程的主要代码: @Override public void run() { // TODO Auto-generated method stub while(true){ if(ticket > 0){//当线程0被调起的时候,当执行到这条判断语句的时候,线程1被调起抢了CPU资源,线程0进入冻结状态. try { Thread.sleep(100);//中断当前活跃的线程,或者

如何解决线程安全问题

http://www.cnblogs.com/dolphin0520/p/3923737.html 一.什么时候会出现线程安全问题? 在单线程中不会出现线程安全问题,而在多线程编程中,有可能会出现同时访问同一个资源的情况,这种资源可以是各种类型的的资源:一个变量.一个对象.一个文件.一个数据库表等,而当多个线程同时访问同一个资源的时候,就会存在一个问题: 由于每个线程执行的过程是不可控的,所以很可能导致最终的结果与实际上的愿望相违背或者直接导致程序出错. 举个简单的例子: 现在有两个线程分别从网

java并发之如何解决线程安全问题

并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务. 而Java并发则由多线程实现的. 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中.(当然这是比较笼统的说法,线程之间是可以交互的,他们也不一定是串行.) 多线程的存在就是压榨cpu,提高程序性能,还能减少一定的设计复杂度(用现实的时间思维设计程序). 这么说来似乎线程就是传说中的银弹了,可事实告诉我们真正的银弹并不存在. 多线程会引出很多难以避免的问题, 如死锁,脏数据,线程管理的额外开销,

解决线程安全问题

线程带来的风险 线程安全性问题 出现安全性问题的需要满足的条件:多线程环境.有共享资源.非原子性操作 活跃性问题 死锁 饥饿 活锁 性能问题 cpu上下文切换会有性能问题(cpu分时间片执行) 锁 自旋锁 自旋其实就是当一个线程获取到锁之后,其他的线程会进行阻塞等待,一直到这个线程释放锁后才能进入 重入锁 & 锁重入 锁重入即在一个对象中对两个方法都加锁了,那么在一个线程获取到其中一个方法的锁后,再执行另外一个方法时就不再需要获取锁了:同时如果一个线程获取到了其中一个方法的锁,那么其他的线程既不