package cn.itcast.hemai2;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 互斥关键是要把同时执行的几个线程里面的东西加上同一把锁,而不是不同的锁。
* 是同时执行的东西加上同一把锁,这是最核心 的东西。下面有两个线程同时间在执行
* 里面执行的有方法,必须加上同一把锁。
* 代码块synchronized (String.class) 如果这个它的锁就是Strin对象 ,但是0
* 如果是同步方法,它的锁对象 不可以由我们指定 ,但是它是Outputer这个对象本身,所以想要
* 和静态代码块互斥,代码块也必须 是这把锁。可以写成synchronized(this)
* 但是如果是静态方法,它的锁就是synchronized(Outputer.class)
* 总结 :
* 1、同步代码块锁由我们指定
* 2、同步方法锁是对象本身
* 3、静态方法锁是对象字节码文件
* @author admin
*Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象。
*Lock就是用来替代synchronized的。
*
*读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,
*那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!
*/
public class LockTest {
/**
* @param args
*/
public static void main(String[] args) {
new LockTest().init();
}
private void init(){
final Outputer outputer = new Outputer();
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("zhangxiaoxiang");
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("lihuoming");
}
}
}).start();
}
static class Outputer{
Lock lock = new ReentrantLock();
public void output(String name){
int len = name.length();
// synchronized (Outputer.class)
// {
lock.lock();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
// }
lock.unlock();
}
public synchronized void output2(String name){
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
public static synchronized void output3(String name){
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
package cn.itcast.hemai2;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象。
读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!
在等待 Condition 时,允许发生“虚假唤醒”,这通常作为对基础平台语义的让步。对于大多数应用程序,这带来的实际影响很小,因为 Condition 应该总是在一个循环中被,并测试正被等待的状态声明。某个实现可以随意移除可能的虚假唤醒,但等待建议应用程序程序员总是假定这些虚假唤醒可能发生,因此总是在一个循环中等待。
一个锁内部可以有多个Condition,即有多路等待和通知,可以参看jdk1.5提供的Lock与Condition实现的可阻塞队列的应用案例,从中除了要体味算法,还要体味面向对象的封装。在传统的线程机制中一个监视器对象上只能有一路等待和通知,要想实现多路等待和通知,必须嵌套使用多个同步监视器对象。(如果只用一个Condition,两个放的都在等,一旦一个放的进去了,那么它通知可能会导致另一个放接着往下走。)
*/
/**
* 这还是原来的代码 ,只是换了某个同步的工具。
*
* @author admin 同步从sync换成Condition wait和notify换成
* 了condition.await(),condition.signal();
*/
public class ConditionCommunication {
/**
* @param args
*/
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 50; i++) {
business.sub(i);
}
}
}).start();
for (int i = 1; i <= 50; i++) {
business.main(i);
}
}
static class Business {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
private boolean bShouldSub = true;
public void sub(int i) {
lock.lock();
try {
while (!bShouldSub) {
try {
condition.await();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (int j = 1; j <= 10; j++) {
System.out.println("sub thread sequence of " + j
+ ",loop of " + i);
}
bShouldSub = false;
condition.signal();
} finally {
lock.unlock();
}
}
public void main(int i) {
lock.lock();
try {
while (bShouldSub) {
try {
condition.await();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (int j = 1; j <= 100; j++) {
System.out.println("main thread sequence of " + j
+ ",loop of " + i);
}
bShouldSub = true;
condition.signal();
} finally {
lock.unlock();
}
}
}
}