线程同步是指多个线程对同一资源(同一对象、同一变量等)进行操做,就会产生线程同步的问题。
java
以下:数组
package org.zhanghua.javase.demo.thread; /** * 线程同步演示 * * @author ZhangHua * */ public class SynchronizedTest1 implements Runnable { Timer timer = new Timer(); public static void main(String[] args) { SynchronizedTest1 test = new SynchronizedTest1(); Thread t1 = new Thread(test); Thread t2 = new Thread(test); t1.setName("t1"); t2.setName("t2"); t1.start(); t2.start(); } @Override public void run() { timer.add(Thread.currentThread().getName()); } } /** * 若是访问公用资源(例如:多个对象同时访问一个资源的时候),就须要同步 * * @author ZhangHua * */ class Timer { private static int num = 0; // 在方法前加关键字synchronized 表示当程序执行到该方法时,锁定当前对象 public synchronized void add(String name) { // synchronized (this) { // 表示在执行这块{}代码的时候,锁定当前对象,其余对象进入不了,只有当这块{}代码执行完了以后,会自动释放当前对象 num++; try { Thread.sleep(1000); } catch (InterruptedException e) { // e.printStackTrace(); } System.out.println(name + "你是第" + num + "个访问timer的线程"); // } } }
若是上面不使用synchronized 线程同步,输出的结果会以下:ide
t2你是第2个访问timer的线程 t1你是第2个访问timer的线程
解决方法:this
一、在方法前加关键字synchronized 表示当程序执行到该方法时,锁定当前对象spa
二、使用synchronized (this) {}表示在执行这块{}代码的时候,锁定当前对象,其余对象进入不了,只有当这块{}代码执行完了以后,会自动释放当前对象线程
2个线程在执行的过程,须要锁定对方对象,才能完成,就会死锁。指针
例如:A 须要锁定B,才能完成;B须要锁定A,才能完成code
package org.zhanghua.javase.demo.thread; /** * 线程死锁演示 * * @author ZhangHua * */ public class DeadLockTest implements Runnable { // 状态值 public int flag = 0; static Object o1 = new Object(); static Object o2 = new Object(); @Override public void run() { System.out.println("flag=" + flag); if (flag == 1) { // 若是flag=1,就执行synchronized{}并锁定,首先锁定o1,而后若是能锁定o2,就能执行完成 synchronized (o1) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o2) { System.out.println("1"); } } } if (flag == 0) { // 若是flag=0,就执行synchronized{}并锁定,首先锁定o2,而后若是能锁定o1,就能执行完成 // 锁定这2个线程就死锁了 synchronized (o2) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o1) { System.out.println("0"); } } } } /** * 结果猜测: 程序卡死了,不动了,该进程永远运行 * * @param args */ public static void main(String[] args) { DeadLockTest d1 = new DeadLockTest(); d1.flag = 1; DeadLockTest d2 = new DeadLockTest(); d2.flag = 0; Thread t1 = new Thread(d1); Thread t2 = new Thread(d2); t1.start(); t2.start(); // 解决死锁的解决方案:能够把锁的对象加大些,若是锁住对象内的2个小对象,有可能发现死锁,那么就加大,锁住整个对象就能够了 } }
解决死锁的解决方案:能够把锁的对象加大些,若是锁住对象内的2个小对象,有可能发现死锁,那么就加大,锁住整个对象就能够了对象
package org.zhanghua.javase.demo.thread; /** * 生产者与消费者演示 * * 模拟一个作汉堡包和吃汉堡包的过程 * * @author Edward * */ public class ProducerConsumerDemo { public static void main(String[] args) { // 大概有以下的概念 // 汉堡包 // 生产者 // 消费者 // 装汉堡包的容器 HamburgerStack stack = new HamburgerStack(); Baker baker = new Baker(stack); Customer customer = new Customer(stack); Thread b1 = new Thread(baker); b1.start(); Thread c1 = new Thread(customer); c1.start(); } } /** * 汉堡包 * * @author Edward * */ class Hamburger { private Integer id; // 编号 用于汉堡包 public Hamburger() { } public Hamburger(Integer id) { this.id = id; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Override public String toString() { return "汉堡包" + id; } } /** * 装汉堡包的容器(先进后出) * * @author Edward * */ class HamburgerStack { private Hamburger[] stack = new Hamburger[10]; // 用数组来装汉堡包,最多能够装10个 private Integer index = 0; // 数组的指针 /** * 向容器中放汉堡包 * * @param hamburger */ public synchronized void push(Hamburger hamburger) { while (index==stack.length) { //就等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); stack[index] = hamburger; // 把汉堡放到第index的位置 index++; // 更新index } /** * 从容器中取汉堡包 * * @return */ public synchronized Hamburger pop() { while (index==0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); index--; return stack[index]; } } /** * 面包师傅(生产者) * * @author Edward * */ class Baker implements Runnable { /** * 生产者怎么生成面包呢? 首先得是一个线程类,由于可能有多个面包师傅 首先有有一个装面包的容器 */ private HamburgerStack stack; public Baker(HamburgerStack stack) { this.stack = stack; } /** * 面包师傅生产面包 * * 假设每一个面包师傅最多生成20个面包,就完成了工做 * */ @Override public void run() { for (int i = 1; i <= 20; i++) { // 生成一个面包 Hamburger hamburger = new Hamburger(i); // 向容器中放面包 stack.push(hamburger); System.out.println("我作了一个:"+hamburger); // 生产一个面包,休息1000毫秒 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } public HamburgerStack getStack() { return stack; } public void setStack(HamburgerStack stack) { this.stack = stack; } } /** * 顾客 吃面包的人(消费者) * * @author Edward * */ class Customer implements Runnable { private HamburgerStack stack; public Customer(HamburgerStack stack) { this.stack = stack; } /** * 消费过程 * * 从装汉堡的容器中,拿出一个汉堡包,而后吃掉 * */ @Override public void run() { for (int i = 1; i <= 20; i++) { // 从容器中拿出一个汉堡包 Hamburger hamburger = stack.pop(); System.out.println("我吃了一个:" + hamburger); // 吃了休息一个1000毫秒 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public HamburgerStack getStack() { return stack; } public void setStack(HamburgerStack stack) { this.stack = stack; } }