多线程产生安全问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。
解决办法:对多条操作共享数据的语句,在一个线程执行完之前,其他线程不允许参与进来.
在JDK1.5之前,java提供了两种专业的解决方式
1,同步代码块
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
2.同步函数
例如:public synchronized void method() 在方法返回值前加上 synchronized关键字.
那么,同步函数用的是哪一个锁呢?
函数需要被对象调用。那么函数都有一个所属对象引用,就是this.所以同步函数使用的锁是this.
在JDK1.5 中提供了多线程安全问题升级解决方案。
Lock:替代了Synchronized
lock();
unlock();
newCondition()
Condition:替代了Object wait notify notifyAll
await();
signal();
signalAll();
将同步Synchronized替换成显示的Lock操作。
将Object中的wait,notify notifyAll,替换成了Condition对象。
通过Lock接口的newCondition()方法,获取绑定到该Lock对象的新Condition对象.不同的Condition对象只负责自己的await()或者singal()操作.
示例:生产者与消费者
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition_con.signal();
}
finally
{
lock.unlock();//释放锁的动作一定要执行。
}
}
public void out()throws InterruptedException
{
lock.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
condition_pro.signal();//condition_pro.await()由对应的signal来唤醒.
}
finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.set("+商品+");
}
catch (InterruptedException e)
{
}
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.out();
}
catch (InterruptedException e)
{
}
}
}
}
class ProducerConsumerDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}