------- android培训、java培训、期待与您交流! ----------
导致多线程出现问题的一个特殊的状态:就绪。具备了执行资格,但是还没有获取资源。
导致安全问题的出现的原因:
1. 多个线程访问出现延迟。
2.线程随机性。
同步代码块:
Java对于多线程的安全问题提供了专业的解决方式。就是同步代码块。
同步代码块格式:
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
同步的前提:
1、必须要有两个或者两个以上的线程。
2、必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
同步代码块的优缺点:
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
还是经典的卖票程序,经过安全处理后:
/** * * 解决卖票程序的安全问题 * 同步代码块 synchronized * */ public class SynchronizedDemo { public static void main(String[] args) { Tic t = new Tic(); 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 Tic implements Runnable { private int tic = 100; Object obj = new Object(); public void run() { while (tic>0) { synchronized(obj) { //为了效果明显这里用了sleep方法,此方法需要指定睡眠时间,单位毫秒,应用需要try{}catch{} try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"--------"+tic--); } } } }
如何找问题:
1,明确哪些代码是多线程运行代码。
2,明确共享数据。
3,明确多线程运行代码中哪些语句是操作共享数据的。
同步函数特点:
如果参数没有就默认是this.
如果被静态修饰就是XX.class。因为静态没有this
/** * 需求: * 银行有一个金库。 * 有两个储户分别存300员,每次存100,存3次。 */ class Bank { private int sum; //下面调用用了多线程,所以这里需要同步 public synchronized void add(int num)//同步函数 { sum += num; System.out.println("sum = "+sum); } } class Cus implements Runnable { //这里只能创建一个银行,所以放在run外面 private Bank b = new Bank(); public void run() { for (int i=0;i<3 ;i++ ) { b.add(100); } } } class BankDemo { public static void main(String[] args) { Cus c = new Cus(); Thread c1 = new Thread(c); Thread c2 = new Thread(c); c1.start(); c2.start(); } }
在多线程里面会发生一种叫做死锁的情况,应尽量避免死锁的发生。
死锁:是指多个进程因竞争系统资源或相互通信而造成的一种僵局
死锁产生的原因:
1.竞争资源:多个进程竞争资源,而资源又不能同时满足其需求
2.进程推进顺序不当:进程申请资源和释放资源的顺序不当
注意:
1.死锁是因资源竞争造成的僵局
2.死锁至少涉及两个进程
3.死锁与部分进程及资源相关
解决死的基本方法:
1.预防死锁:设置某些限制条件,通过破坏死锁产生的条件来预防死锁
2.避免死锁:在资源的动态分配过程中,用某种方法来防止系统进入不安全状态
3.检测死锁及解除死锁:系统定期检测是否出现死锁,若出现则解除死锁/** * * 死锁程序的演示 * 尽量避免!!! * */ public class MyLock { public static void main(String[] args) { Thread t1 = new Thread(new Test(true)); Thread t2 = new Thread(new Test(false)); t1.start(); t2.start(); } } //声明一个类,里面创建两个对象,代表两个锁 class Lock { static Object locka = new Object();//静态只能访问静态 static Object lockb = new Object(); } //声明一个类,实现Runnable接口,演示死锁的多线程类 class Test implements Runnable { private boolean flag; Test (boolean flag) { this.flag = flag; } public void run() { if (flag) { while(true) { synchronized (Lock.locka) { System.out.println(Thread.currentThread().getName()+"------"+"if locka"); synchronized (Lock.lockb) { System.out.println(Thread.currentThread().getName()+"------"+"if lockb"); } } } } else { while (true) { synchronized (Lock.lockb) { System.out.println(Thread.currentThread().getName()+"------"+"else lockb"); synchronized (Lock.locka) { System.out.println(Thread.currentThread().getName()+"------"+"else locka"); } } } } } }