主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。
举例说明(对下面的题用lock进行了改写):
package com.huawei.interview;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
publicclass ThreadTest {
privateintj;
private Lock lock = new ReentrantLock();
publicstaticvoid main(String[] args) {
ThreadTest tt = new ThreadTest();
for(int i=0;i<2;i++)
{
new Thread(tt.new Adder()).start();
new Thread(tt.new Subtractor()).start();
}
}
privateclass Subtractor implements Runnable
{
@Override
publicvoid run() {
while(true)
{
lock.lock();
try
{
System.out.println("j--=" + j--);
}finally
{
lock.unlock();
}
}
}
}
privateclass Adder implements Runnable
{
publicvoid run() {
while(true)
{
lock.lock();
try
{
System.out.println("j++=" + j++);
}finally
{
lock.unlock();
}
}
}
}
}
以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。
public class ThreadTest1
{
private int j;
public static void main(String args[]){
ThreadTest1 tt=new ThreadTest1();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(inti=0;i<2;i++){
Thread t=new Thread(inc);
t.start();
t=new Thread(dec);
t.start();
}
}
private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+"-inc:"+j);
}
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
}
class Inc implements Runnable{
public void run(){
for(int i=0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
public void run(){
for(int i=0;i<100;i++){
dec();
}
}
}
}
----------随手再写的一个-------------
class A
{
JManger j =new JManager();
main()
{
newA().call();
}
void call
{
for(inti=0;i<2;i++)
{
newThread(
newRunnable(){ public void run(){while(true){j.accumulate()}}}
).start();
newThread(new Runnable(){ public void run(){while(true){j.sub()}}}).start();
}
}
}
class JManager
{
privatej = 0;
publicsynchronized void subtract()
{
j--
}
publicsynchronized void accumulate()
{
j++;
}
}
最终的程序代码如下:
publicclass ThreadTest {
publicstaticvoid main(String[] args) {
new ThreadTest().init();
}
publicvoid init()
{
final Business business = new Business();
new Thread(
new Runnable()
{
publicvoid run() {
for(int i=0;i<50;i++)
{
business.SubThread(i);
}
}
}
).start();
for(int i=0;i<50;i++)
{
business.MainThread(i);
}
}
privateclass Business
{
booleanbShouldSub = true;//这里相当于定义了控制该谁执行的一个信号灯
publicsynchronizedvoid MainThread(int i)
{
if(bShouldSub)
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
for(int j=0;j<5;j++)
{
System.out.println(Thread.currentThread().getName() + ":i=" + i +",j=" + j);
}
bShouldSub = true;
this.notify();
}
publicsynchronizedvoid SubThread(int i)
{
if(!bShouldSub)
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
for(int j=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName() + ":i=" + i +",j=" + j);
}
bShouldSub = false;
this.notify();
}
}
}
备注:不可能一上来就写出上面的完整代码,最初写出来的代码如下,问题在于两个线程的代码要参照同一个变量,即这两个线程的代码要共享数据,所以,把这两个线程的执行代码搬到同一个类中去:
package com.huawei.interview.lym;
publicclass ThreadTest {
privatestaticbooleanbShouldMain = false;
publicstaticvoid main(String[] args){
new Thread(
new Runnable()
{
publicvoid run()
{
for(int i=0;i<50;i++)
{
synchronized (ThreadTest.class) {
if(bShouldMain)
{
try {
ThreadTest.class.wait();}
catch(InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0;j<10;j++)
{
System.out.println(
Thread.currentThread().getName()+
"i=" + i + ",j=" + j);
}
bShouldMain = true;
ThreadTest.class.notify();
}
}
}
}
).start();
for(int i=0;i<50;i++)
{
synchronized (ThreadTest.class) {
if(!bShouldMain)
{
try {
ThreadTest.class.wait();}
catch(InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0;j<5;j++)
{
System.out.println(
Thread.currentThread().getName() +
"i=" + i + ",j=" + j);
}
bShouldMain = false;
ThreadTest.class.notify();
}
}
}
}
下面使用jdk5中的并发库来实现的:
import java.util.concurrent.Executors;
importjava.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
importjava.util.concurrent.locks.Condition;
public class ThreadTest
{
privatestatic Lock lock = new ReentrantLock();
privatestatic Condition subThreadCondition = lock.newCondition();
privatestatic boolean bBhouldSubThread = false;
publicstatic void main(String [] args)
{
ExecutorServicethreadPool = Executors.newFixedThreadPool(3);
threadPool.execute(newRunnable(){
publicvoid run()
{
for(inti=0;i<50;i++)
{
lock.lock();
try
{
if(!bBhouldSubThread)
subThreadCondition.await();
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ",j=" + j);
}
bBhouldSubThread= false;
subThreadCondition.signal();
}catch(Exceptione)
{
}
finally
{
lock.unlock();
}
}
}
});
threadPool.shutdown();
for(inti=0;i<50;i++)
{
lock.lock();
try
{
if(bBhouldSubThread)
subThreadCondition.await();
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ",j=" + j);
}
bBhouldSubThread= true;
subThreadCondition.signal();
}catch(Exceptione)
{
}
finally
{
lock.unlock();
}
}
}
}