1、死锁
(1)不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的向步资源,就形成了线程的死锁。
(2)出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续。
2、解决方法
(1)专门的算法、原则。
(2)尽量减少同步资源的定义
(3)尽量避免嵌套同步
1、格式:
2、说明:
(1)操作共享数据的代码,及需要被同步的代码;
(2)共享数据,多个线程共同操作的变量;
(3)同步监视器,俗称锁,如何一个类的对象都可以充当锁。
3、要求:多个线程必须要公用同一把锁
4、例子:4个窗口拿100个号码
class TakeNumber_1 implements Runnable{ private int number = 100; Object object=new Object(); //2.实现类去实现Runnable中抽象方法run() @Override public void run() { while (true){ synchronized (object) { if (number > 0) { //设置0.1秒的睡眠等待 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "拿到号码:" + number); number--; } else { break; } } } } } public class Synchronization { public static void main(String[] args) { //3.创建实现类的对象 TakeNumber_1 takeNumber_1 = new TakeNumber_1(); //4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象 Thread t1 = new Thread(takeNumber_1,"窗口一"); Thread t2 = new Thread(takeNumber_1,"窗口二"); Thread t3 = new Thread(takeNumber_1,"窗口三"); Thread t4 = new Thread(takeNumber_1,"窗口四"); //5.通过Thread类的对象调用start() t1.start(); t2.start(); t3.start(); t4.start(); } }
1、对于继承Thread类时,需要将同步方法设为静态即可
private static synchronized void show()
2.例子:4个窗口拿100个号码
class TakeNumber01 implements Runnable{ private int number = 100; //2.实现类去实现Runnable中抽象方法run() @Override public void run() { while (true) { show(); } } private synchronized void show(){ //同步监视器:this if (number>0){ //设置0.1秒的睡眠等待 try{ Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"拿到号码:"+number); number--; } } } public class TakeTest01 { public static void main(String[] args) { TakeNumber01 takeNumber01 = new TakeNumber01(); Thread t1 = new Thread(takeNumber01,"窗口一"); Thread t2 = new Thread(takeNumber01,"窗口二"); Thread t3 = new Thread(takeNumber01,"窗口三"); Thread t4 = new Thread(takeNumber01,"窗口四"); t1.start(); t2.start(); t3.start(); t4.start(); } }
1、Lock锁
(1)从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。
(2)java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
(3)ReentrantLock类实现了Lock,它拥有与 synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。
2、例子:4个窗口拿100个号码
class Windo implements Runnable { private int number = 100; //1.实例化ReentrantLock private ReentrantLock lock=new ReentrantLock(true); @Override public void run() { while (true) { try { //2.调用锁定的方法:lock() lock.lock(); if (number > 0) { //设置0.1秒的睡眠等待 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "拿到号码:" + number); number--; } }finally { //3.调用解锁方法:unlock() lock.unlock(); } } } } public class LockTest { public static void main(String[] args) { Windo w1 = new Windo(); Thread t1 = new Thread(w1, "窗口一"); Thread t2 = new Thread(w1, "窗口二"); Thread t3 = new Thread(w1, "窗口三"); t1.start(); t2.start(); t3.start(); } }
1、Synchronized和lock的异同
(1)相同:二者都可以解决线程安全问题
(2)不同:synchronized机制在执行完相应的同步代码后,自动的释放同步监视器
lock需要手动的启动同步(lock())和结束同步(unlock())
2、sleep()和wait()的异同
(1)相同:一旦执行方法,都可以使当前的线程进入阻塞状态
(2)不同:
1) 两个方法声明的位置不同:Thread类中声明sleep(),Object类中声明wait()
2) 调用要求不同:sleep()可以在任何需要的场景下调用,wait()必须使用在同步代码块或同步方法中
3) 关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。
原文:https://www.cnblogs.com/NiShilin/p/15022350.html