在实现Runnable接口后,可以通过多个start方法来调用同一段代码资源,这也会导致一个问题就是资源可能不同步。
解决资源不同步的方法是,在同一时间段内,只允许一个线程来操作这个对象或方法,其他线程需等待此线程访问结束后才能继续执行,将其锁住。
关键字synchronized:表示只能有一个线程执行synchronized所声明的代码块或方法,并且在执行过程中其他方法不能锁定这个对象 。使用方式有同步代码块与同步方法,两者功能一样。
只能有一个同步方法访问该对象,其他方法若是同步的则不能访问该对象,非同步方法反而可以访问该对象(傻啦吧唧)
同步代码块
public class Test { public static void main(String[] args) { MyThread thread = new MyThread(); Thread t1 = new Thread(thread,"t1"); Thread t2 = new Thread(thread,"t2"); t1.start(); t2.start(); } } class MyThread implements Runnable { static int num = 5; public void run() { //synchronized (this) {//表示只能有一个线程执行下面这段代码块,为下面这段代码块加锁 if (num > 0) { for (int i = 1;i < 6;i++) { num--; try{ Thread.sleep(20);//起到放大效果作用 }catch(InterruptedException e) { System.out.println("线程休眠被打断"); } System.out.println(Thread.currentThread().getName() + "取走还剩" + num); } } //} } }
使用了同步代码块之后:
同步方法进一步探讨一
public class Test { public static void main(String[] args) throws Exception { MyThread thread = new MyThread(); Thread t1 = new Thread(thread,"t1"); t1.start(); Thread.sleep(10); thread.m2(); } } class MyThread implements Runnable { int num = 1; public synchronized void run() {//仅表示锁住这个方法不能同时被其它线程执行,并不能锁住这个对象不被其他线程执行 num = 1000; try{ Thread.sleep(5000); System.out.println(num); }catch(InterruptedException e) { System.out.println("休眠中被打断"); } } void m2() { num = 2000; System.out.println(num); } }
结果
讨论二
public class Test { public static void main(String[] args) throws Exception { MyThread thread = new MyThread(); Thread t1 = new Thread(thread,"t1"); t1.start(); Thread.sleep(10); thread.m2(); } } class MyThread implements Runnable { int num = 1; public synchronized void run() {//仅表示锁住这个方法不能同时被其它线程执行,并不能锁住这个对象不被其他线程执行 num = 1000; try{ Thread.sleep(5000); System.out.println(num); }catch(InterruptedException e) { System.out.println("休眠中被打断"); } } synchronized void m2() {//在run方法上锁期间其他线程运行时并不能为对象上第二把锁 num = 2000; System.out.println(num); } }
结果