黑马程序员 Java基础学习笔记 线程安全问题

时间:2023-02-19 13:14:43

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Unity开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ------------------------------------------ 

多线程的运行出现啦安全问题

问题的原因:

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

解决办法:

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

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

   synchronized(对象){   需要被同步的代码 }//谁在使用共享数据

对象如果有锁。持有锁的线程可以在同步中执行。没有锁的线程即使获取cpu的执行权,也进不去。因为没有获取锁。

同步的前提:

1必须要有两个或两个以上的线程。  2必须是多个线程使用同一个锁。  必须保证同步中只能有一个线程在运行。

好处:解决了多线程的安全问题。 弊端:多个线程需要判断锁,较为消耗资源。

如何找问题(安全问题)

1明确那些代码是多线程运行的代码。      2明确共享数据

3明确多线程代码中哪些语句是操作共享数据

同步函数

同步函数用的是哪个锁呢?

函数需要被对象调用。那么函数都有一个所属对象的引用。就是this,所以同步函数使用的锁是this。

如果同步函数被静态修饰后,使用的锁是什么呢?

静态进内存时,内存中没有本类对象,但是一定有该类对象对应的字节码文件对象。 类名.class  该对象的类型是class

静态的同步方法,使用的锁是该方法所在类的字节码文件对象。  类名.class

死锁

同步嵌套,而且不是同一个锁。

卖票例子


//卖票程序。多个窗口卖票。
/*
创建线程的第二种方法:实现Runnable接口。
1 定义类实现Runnable接口。
2 覆盖Runnable接口中的run的方法。
3 通过Thread类建立线程对象。
4 将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
5 调用Thread的start()方法并调用Runnable接口子类的run方法。
*/
class Ticket implements Runnable
{
private  int tick=100;
Object obj=new Object();
public void run()
{
while(true)
{
synchronized(obj)//加入同步代码块,解决多线程安全问题。
{
if(tick>0)
{
System.out.println(Thread.currentThread().getName()+"....sale:"+tick--);
}
}
}

}
}


class  TicketDemo1
{
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);
Thread t4=new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}

死锁的例子


//死锁程序
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag=flag;
}
public void run()
{
if(flag)
{
synchronized(MyLock.locka)
{
System.out.println("if locka");
synchronized(MyLock.lockb)
{
System.out.println("if lockb");
}
}
}else
{
synchronized(MyLock.lockb)
{
System.out.println("else lockb");
synchronized(MyLock.locka)
{
System.out.println("else locka");
}
}
}

}
}


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


class DeadLockTest 
{
public static void main(String[] args) 
{
Thread t1=new Thread(new Test(true));
Thread t2=new Thread(new Test(false));
t1.start();
t2.start();
}
}

你要我的锁,我要你的锁。造成死锁。

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Unity开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! --------------------------------