synchronized
package lock的使用;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MySynchronized {
static String now() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
String now = sdf.format(d);
//返回时间
return now;
}
//log方法
static void log(String msg) {
System.out.printf("%s:%s%s%n",now(),Thread.currentThread().getName(),msg);
}
public static void main(String[] args) {
final Object someObject = new Object();
Thread t1 = new Thread() {
@Override
public void run() {
//进度说明
log("线程已经运行");
log("线程试图占有someObject");
//同步对象
synchronized (someObject) {//synchronized同步代码块内的代码为关键逻辑代码,需要被保护的,以免产生脏数据
log("线程占有someObject");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log("释放someObject");
}
}
};
t1.setName("T1");//设置名字
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
//进度说明
log("线程已经运行");
log("线程试图占有someObject");
//同步对象
synchronized (someObject) {
log("线程占有someObject");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log("释放someObject");
}
}
};
t2.setName("T2");
t2.start();
}
}
Lock接口
package lock的使用;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestMyLock {
//时间
static String now() {
SimpleDateFormat sdf = new SimpleDateFormat();
Date d = new Date();
String now = sdf.format(d);
return now;
}
//简化的说明
static void log(String msg) {
System.out.printf("%s:%s%s%n",now(),Thread.currentThread().getName(),msg);
}
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Thread t1 = new Thread() {
@Override
public void run() {
log("线程已经运行");
log("线程试图占有lock");
lock.lock();
log("线程成功占有lock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
log("线程结束");
//关掉lock
lock.unlock();
}
}
};
t1.setName("T1");
t1.start();
try {
//让t1飞两秒
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Thread t2 = new Thread() {
@Override
public void run() {
log("线程已经运行");
log("线程试图占有lock");
lock.lock();//lock.lock()与lock.unlock()之间的代码为关键逻辑代码,需要被保护的,以免产生脏数据
log("线程成功占有lock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
log("线程结束");
//关掉lock
lock.unlock();
}
}
};
t2.setName("T2");
t2.start();
}
}
tyyLock()用法
package lock的使用;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestMyTrylock {
//时间
static String now() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
String now = sdf.format(d);
return now;
}
//规范化的输出
static void log(String msg) {
System.out.printf("%s:%s%s%n",now(),Thread.currentThread().getName(),msg);
}
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Thread t1 = new Thread() {
@Override
public void run() {
boolean loked = false;//记录是否线程占用成功lock对象
log("线程已经运行");
log("线程视图占有lock对象");
try {
//设置线程最大等待时间两秒
loked = lock.tryLock(2,TimeUnit.SECONDS);
if(loked) {
log("线程占有lock对象,并进行5秒的运算");
Thread.sleep(5000);
}else {
log("线程经过两秒的努力没有成功占有lock对象");
}
log("线程结束");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(loked) {
lock.unlock();
}
}
}
};
t1.setName("T1");
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
boolean loked = false;//记录是否线程占用成功lock对象
log("线程已经运行");
log("线程视图占有lock对象");
try {
loked = lock.tryLock(2,TimeUnit.SECONDS);
if(loked) {
log("线程占有lock对象,并进行5秒的运算");
Thread.sleep(5000);
}else {
log("线程经过两秒的努力没有成功占有lock对象");
}
log("线程结束");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(loked) {
lock.unlock();
}
}
}
};
t2.setName("T2");
t2.start();
}
}
使用lock进行线程交互
package lock的使用;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestMyLock {
//时间
static String now() {
SimpleDateFormat sdf = new SimpleDateFormat();
Date d = new Date();
String now = sdf.format(d);
return now;
}
//简化的说明
static void log(String msg) {
System.out.printf("%s:%s%s%n",now(),Thread.currentThread().getName(),msg);
}
public static void main(String[] args) {
Lock lock = new ReentrantLock();
//后边释放锁,唤醒其他线程需要使用下边这个类
Condition condition = lock.newCondition();
Thread t1 = new Thread() {
@Override
public void run() {
log("线程已经运行");
log("线程试图占有lock");
lock.lock();
log("线程成功占有lock");
try {
Thread.sleep(5000);
//让线程临时释放锁让其他线程得到lock对象并运行
//此处使用lock的释放方法与synchronized略有不同
log("线程临时释放锁");
condition.await();//释放操作与synchronized的wait()对应
log("线程重新获得lock对象进行五秒的操作");
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
log("线程结束");
//关掉lock
lock.unlock();
}
}
};
t1.setName("T1");
t1.start();
try {
//让t1先跑两秒
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Thread t2 = new Thread() {
@Override
public void run() {
log("线程已经运行");
log("线程试图占有lock");
lock.lock();//lock.lock()与lock.unlock()之间的代码为关键逻辑代码,需要被保护的,以免产生脏数据
log("线程成功占有lock并进行5秒的操作");
try {
Thread.sleep(5000);
condition.signal();//唤醒操作与synchronized的notify()对应 还有个signalAll()与notifyAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
log("线程结束");
//关掉lock
lock.unlock();
}
}
};
t2.setName("T2");
t2.start();
}
}
简单描述synchronized关键字和Lock接口的区别
前者是java关键字是内置语言实现,后者是接口,然后就是lock需要每次结束手动释放锁,否则会造成死锁,再者使用synchronized容易造成死锁,必须代码逻辑严密不出错才能避免死锁,而lock有个trylock()方式可以设置抢占资源的时间,过了时间自动不抢了,有效避免死锁,然后就是synchronied中线程交互,被占用调用wait(),notify(),notifyAll()均来自Obejct超级父类。而lock接口中使用await(),signal(),signalAll()来自于Condition接口;