Java:多线程<二> 同步
由于多线程的访问出现延迟和线程的随机性,在使用多线程时往往会伴随安全性的问题,这些问题一旦出现将会是非常严重的。为了解决这种安全性问题,synchronized出现了。
synchronized用法一,放在方法内,必须传一个对象obj
synchronized(obj) { //需要被同步的代码 }synchronized用法二,放在方法上,不需要传对象
public synchronized void method() { //该方法体中所有的代码都被同步了 }例子:银行有个小金库,初始为0,有一天有两个富商来存金币,每人每次同时存100金币,没有使用同步的多线程代码
class Bank { private int gold=0; public void add(int num) { try { Thread.sleep(10); gold += num; } catch (Exception e) { System.out.println("银行内部错误,暂停服务!"); System.exit(0); } System.out.println("金库里有"+gold+"金币"); } } class Business implements Runnable { private Bank b = new Bank(); public void run() { for(int i=0;i<3;i++) { b.add(100); } } } class StoreGold { public static void main(String[] args) { Business b = new Business(); Thread t1 = new Thread(b,"张三"); Thread t2 = new Thread(b,"李四"); t1.start(); t2.start(); } }
运行时,就有可能出现金库里有500金币两次等等错误情况,其原因是gold没有被同步,有被同时使用一个值的情况。在Bank的add方法中应该加上同步,如下
class Bank { private int gold=0; public void add(int num) { synchronized(this) { try { Thread.sleep(10); gold += num; } catch (Exception e) { System.out.println("银行内部错误,暂停服务!"); System.exit(0); } } System.out.println("金库里有"+gold+"金币"); } }也可以把synchronized加在方法上,这样的写法边简单了,但是同步的内容就多了。同步函数的锁是this。
class Bank { private int gold=0; public synchronized void add(int num) { try { Thread.sleep(10); gold += num; } catch (Exception e) { System.out.println("银行内部错误,暂停服务!"); System.exit(0); } System.out.println("金库里有"+gold+"金币"); } }虽然同步可以让线程在处理某些事务时更为安全,但同时由于每个线程都多了拿锁、等待、释放锁等操作,所以会影响程序运行的速率。
那么什么代码需要被同步呢?
1,明确哪些代码是多线程运行代码
2,明确共享数据
3,明确多线程运行代码中哪些语句是操作共享数据的
同步使用的是什么锁呢?
1,函数使用的锁是this
2,静态函数使用的锁是类名.class,字节码文件对象