线程同步
线程同步的基本方法主要为使用synchronized 关键字来修饰代码块或方法。
实例如下
synchronized(obj)//obj成为同步监视器,通常为要被并发访问的共享资源
{}
public synchronized void do() //synchronized修饰方法,则默认的同步监视器为this,因此,任何时刻只有一个线程能使用do()访问this。
{}
Lock 同步锁
除了synchronized关键字外,Java还提供了一种锁机制。
通过锁机制,可以更灵活地控制共享资源地同步。
下面举个例子:
首先定义一个共享资源类Info
public class Info {
private int amount;
public Info(int amount)
{
this.amount = amount;
}
public void minus(int a) //定义一个减少amount的方法
{
System.out.println("the amount now is " + this.amount);
this.amount -= a;
System.out.println("the amount now is " + this.amount);
}
public void add(int b) // 定义一个增加amount的方法
{
System.out.println("the amount now is " + this.amount);
this.amount += b;
System.out.println("the amount now is " + this.amount);
}
}
接下来定义两个线程,功能为操作Info类的amount变量。
首先是减少amount的线程
public class MinusThread extends Thread {
private Info i;
private final ReentrantLock rl = new ReentrantLock();
public MinusThread(Info i)
{
this.i = i;
}
public void run()
{
rl.lock();
min(i);
rl.unlock();
}
public void min(Info info)
{
for(int i = 0; i < 100; i ++)
{
info.minus(20);
}
}
}
其次是增加amount的线程
public class PlusThread extends Thread {
private Info i;
private final ReentrantLock lock = new ReentrantLock(); //定义一个锁
public PlusThread(Info i)
{
this.i = i;
}
public void run() {
lock.lock();
addi(i);
lock.unlock();
}
public void addi(Info info)
{lock.lock();
for(int i = 0 ; i < 100; i ++)
{
info.add(50);
}
}
}
接下来写个main函数开始运行
public static void main(String[] args)
{
Info i = new Info(3000,1995,"abc");
Info j = new Info(3000,1995,"abc");
SimpleThread st = new SimpleThread(i);
MinusThread mt = new MinusThread(j);
st.start();
mt.start();
}
首先看到,我们定义了两个Info实例,并且分别传给两个线程。运行这个main,我们可以看到,两个线程实际上是同时进行的。因为两个线程并没有使用共享资源,所以两个线程互不影响。
接下来,我们定义一个Info实例并传给两个线程,这就使得两个线程共享同一个Info类。
public static void main(String[] args)
{
Info i = new Info(3000,1995,"abc");
SimpleThread st = new SimpleThread(i);
MinusThread mt = new MinusThread(i);
st.start();
mt.start();
}
运行程序,可以看到由于使用同一个Info实例,由于lock的作用,两个线程实际上是按顺序运行的。