本帖最后由 余清兰 于 2012-7-27 08:36 编辑
Synchronized关键字定义的有同步代码块和同步函数Synchronized(对象) { 需要被同步的代码(操作的是共享数据的代码); } 对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。 任何对象都可作为锁,但只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。
同步函数的时候,非静态的函数的锁是this,静态的函数的锁是该类的字节码文件对象
当同步中嵌套同步,而锁却不同时,就会出现死锁。
具体的说:synchronized锁是隐式的锁,多线程时每次执行锁里的代码都要先进行判断锁是否释放,释放了才能持有锁,执行完代码后,就自动释放锁,加锁和释放锁都是隐式的
操作线程的wait()和notify()等方法都是继承的Object的,而且它要么用notify()唤醒线程池中的第一个被等待的线程,要么用notifyAll()唤醒所有被等待的线程,
它不能唤醒对方的线程:比如在多线程间通讯时,多个线程处理同一个资源,处理动作却不一样,要唤醒对方,可以创建多个Condition对象,用signal()方法来唤醒对方的等待线程。
JDK1.5中提供了多线程升级解决方案,将同步synchronized替换成显示lock操作(显示的锁机制)。将object中的wait,notify,notifyAll,替换成了Condition对象,
一个锁可以定义多个Condition对象,该对象可以Lock锁进行获取,可以实现本方只唤醒对方的等待线程。
下面用生产者和消费者的例子,分别用两种方式来体现,就可以看到区别了 - class res
- {
- private String name;
- private int count = 1;
- private boolean flag = false;
- public synchronized void set(String name)
- {
- while(flag)
- try
- {
- wait();
- }
- catch (Exception e)
- {
- }
- this.name=name+"=="+count++;
- System.out.println(Thread.currentThread().getName()+"生产者..."+this.name);
- flag = true;
- this.notifyAll();
- }
- public synchronized void out()
- {
- while(!flag)
- try
- {
- wait();
- }
- catch (Exception e)
- {
- }
- System.out.println(Thread.currentThread().getName()+"消费者........"+this.name);
- flag = false;
- this.notifyAll();
- }
- }
- class Producer implements Runnable
- {
- private res r;
- Producer(res r)
- {
- this.r = r;
- }
- public void run()
- {
- while (true)
- {
- r.set("商品");
- }
- }
- }
- class Consumer implements Runnable
- {
- private res r;
- Consumer(res r)
- {
- this.r = r;
- }
- public void run()
- {
- while (true)
- {
- r.out();
- }
-
- }
- }
- class resDemo
- {
- public static void main(String[] args)
- {
- res r = new res();
- Producer pro = new Producer(r);
- Producer pro1 = new Producer(r);
- Consumer con = new Consumer(r);
- Consumer con1 = new Consumer(r);
- Thread t1 = new Thread(pro);
- Thread t2 = new Thread(con);
- Thread t3 = new Thread(pro1);
- Thread t4 = new Thread(con1);
- t1.start();
- t2.start();
- t3.start();
- t4.start();
- }
- }
复制代码 分析:当出现多个线程同时生产和消费时,为了避免重复生产同一个商品的情况,要用while循环,让每个线程获取执行权后都要判断标记flag,
为了避免所有线程都是等待状态,只能用notifyAll()唤醒所有线程池中的等待线程,若用notify容易出现只唤醒本方线程的情况,这样的话,若唤醒了本方线程,会出现全部等待情况,
若都唤醒了,那在消费者还没消费完商品的时候,有可能生产者的线程唤醒了又去判断锁,但又不能执行里面的代码(因为要等消费者消费完),每次判断锁都很消耗资源。
换成显示的锁后,就可以只唤醒对方的线程,就可以解决以上问题。 |