java锁分为对象锁,类锁,
synchronized就是熟知的代码同步块。
加锁一个方法块,根据锁的机制上锁的只是这个对象,
package hw.lock;
/**
*
*
* @author huangwei
* 2017 10 20
*/
public class Producer extends Thread{
int num=1;
public synchronized int count() {
while(num<10) {
System.out.println(Thread.currentThread() +" "+num++);//输出当前线程
}
try {
Thread.sleep(500);
}catch (Exception e) {
// TODO: handle exception
}
return num;
}
public void run() {
count();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Producer aProducer=new Producer();
Producer bProducer=new Producer();
aProducer.start();
bProducer.start();
}
}
输出为这样
Thread[Thread-1,5,main] 1
Thread[Thread-0,5,main] 1
Thread[Thread-0,5,main] 2
Thread[Thread-0,5,main] 3
Thread[Thread-0,5,main] 4
Thread[Thread-0,5,main] 5
Thread[Thread-0,5,main] 6
Thread[Thread-0,5,main] 7
Thread[Thread-0,5,main] 8
Thread[Thread-0,5,main] 9
Thread[Thread-1,5,main] 2
Thread[Thread-1,5,main] 3
Thread[Thread-1,5,main] 4
Thread[Thread-1,5,main] 5
Thread[Thread-1,5,main] 6
Thread[Thread-1,5,main] 7
Thread[Thread-1,5,main] 8
Thread[Thread-1,5,main] 9
说明如果只是对方法上锁的话,那么实际上会对当前的对象上锁,而我们实现了两个对象,所以并没有实现同步。
package hw.lock;
/**
*
*
* @author huangwei
* 2017 10 20
*/
public class Producer extends Thread{
int num=1;
public int count() {
synchronized (this) {
while(num<10) {
System.out.println(Thread.currentThread() +" "+num++);//输出当前线程
}
try {
Thread.sleep(500);
}catch (Exception e) {
// TODO: handle exception
}
}
return num;
}
public void run() {
count();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Producer aProducer=new Producer();
Producer bProducer=new Producer();
aProducer.start();
bProducer.start();
}
}
对当前对象进行上锁 输出结果依旧为没有上锁的样子
Thread[Thread-0,5,main] 1
Thread[Thread-1,5,main] 1
Thread[Thread-0,5,main] 2
Thread[Thread-1,5,main] 2
Thread[Thread-0,5,main] 3
Thread[Thread-0,5,main] 4
Thread[Thread-0,5,main] 5
Thread[Thread-0,5,main] 6
Thread[Thread-0,5,main] 7
Thread[Thread-0,5,main] 8
Thread[Thread-0,5,main] 9
Thread[Thread-1,5,main] 3
Thread[Thread-1,5,main] 4
Thread[Thread-1,5,main] 5
Thread[Thread-1,5,main] 6
Thread[Thread-1,5,main] 7
Thread[Thread-1,5,main] 8
Thread[Thread-1,5,main] 9
那对于两个不同的线程对象 我们要上锁的其实就是公有的属性,或者说就是静态属性。
package hw.lock;
/**
*
*
* @author huangwei
* 2017 10 20
*/
public class Producer extends Thread{
static int num=1;
public int count() {
synchronized (Producer.class) {
while(num<10) {
System.out.println(Thread.currentThread() +" "+num++);//输出当前线程
}
try {
Thread.sleep(500);
}catch (Exception e) {
// TODO: handle exception
}
}
return num;
}
public void run() {
count();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Producer aProducer=new Producer();
Producer bProducer=new Producer();
aProducer.start();
bProducer.start();
}
}
Thread[Thread-1,5,main] 1
Thread[Thread-1,5,main] 2
Thread[Thread-1,5,main] 3
Thread[Thread-1,5,main] 4
Thread[Thread-1,5,main] 5
Thread[Thread-1,5,main] 6
Thread[Thread-1,5,main] 7
Thread[Thread-1,5,main] 8
Thread[Thread-1,5,main] 9
如果是两个对象操作静态变量,对XX.class进行上锁就可以实现,对类上锁同步静态变量方法以及常量。
对于静态方法的synchronized就相当于给这个方法所在的这个内存块添加了一个监视器,
在类加载的时候,类的基本信息和一些常量和今天变量都保存在jvm内存的方法区,
对synchronized(XX.class) 就等于对这个类的所有信息加上 监视器,一个线程进行访问计数+1,释放-1,不为0就一直阻塞其他线程访问。
而类初始化的实例对象则放在了jvm内存的堆区
而对实例对象的上锁就相当于监视这个实例对象,而不同的对象在不同块 并不能实现同步。
对于同一个对象实例
未上锁时
package hw.lock;
/**
*
*
* @author huangwei
* 2017 10 20
*/
public class Producer {
int num=1;
public int count() {
while(num<10) {
System.out.println(Thread.currentThread().getName() +" "+num++);//输出当前线程
}
try {
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
return num;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
final Producer aProducer=new Producer();
//Producer bProducer=new Producer();
Thread test1=new Thread(new Runnable() {
@Override
public void run() {
aProducer.count();
}
});
Thread test2=new Thread(new Runnable() {
@Override
public void run() {
aProducer.count();
}
});
test1.start();
test2.start();
//bProducer.start();
}
}
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 3
Thread-0 4
Thread-1 5
Thread-0 6
Thread-1 7
Thread-0 8
Thread-1 9
对其当前对象上锁
package hw.lock;
/**
*
*
* @author huangwei
* 2017 10 20
*/
public class Producer {
int num=1;
public int count() {
synchronized (this) {
while(num<10) {
System.out.println(Thread.currentThread().getName() +" "+num++);//输出当前线程
}
try {
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
return num;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
final Producer aProducer=new Producer();
//Producer bProducer=new Producer();
Thread test1=new Thread(new Runnable() {
@Override
public void run() {
aProducer.count();
}
});
Thread test2=new Thread(new Runnable() {
@Override
public void run() {
aProducer.count();
}
});
test1.start();
test2.start();
//bProducer.start();
}
}
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
由于num一直由第一个线程执行没有释放,所以第二个线程由于大于10直接结束。
直观一点
num声明在方法内
package hw.lock;
/**
*
*
* @author huangwei
* 2017 10 20
*/
public class Producer {
public int count() {
int num=1;
synchronized (this) {
while(num<10) {
System.out.println(Thread.currentThread().getName() +" "+num++);//输出当前线程
}
try {
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
return num;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
final Producer aProducer=new Producer();
//Producer bProducer=new Producer();
Thread test1=new Thread(new Runnable() {
@Override
public void run() {
aProducer.count();
}
},"test1");
Thread test2=new Thread(new Runnable() {
@Override
public void run() {
aProducer.count();
}
},"test2");
test1.start();
test2.start();
//bProducer.start();
}
}
输出就为这样
test2 1
test2 2
test2 3
test2 4
test2 5
test2 6
test2 7
test2 8
test2 9
test1 1
test1 2
test1 3
test1 4
test1 5
test1 6
test1 7
test1 8
test1 9
简单的生产者消费者模型
package hw.lock;
/**
*
*
* @author huangwei
* 2017 10 20
*/
public class Producer {
int pnum=0;
public int count() {
int num=1;
synchronized (this) {
while(num<10) {
System.out.println(Thread.currentThread().getName() +" "+num++);//输出当前线程
}
try {
Thread.sleep(5000);
}catch (Exception e) {
// TODO: handle exception
}
}
return num;
}
public void produce() {//生产者
synchronized (this) {
try {
if(pnum>10) {
this.wait();//数量上限等待
}
this.notify();//唤醒进程
pnum++;
System.out.println("生产者生产:1,还剩下:"+this.pnum);
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
}
public void customer() {//消费者
synchronized (this) {
try {
if(pnum>0) {
this.notify();//可以取 唤醒
pnum--;
System.out.println("消费者消费:1,还剩下:"+this.pnum);
}else{
System.out.println("消费者消费:0,储量不足");
this.wait();//否则等待
}
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
final Producer aProducer=new Producer();
//Producer bProducer=new Producer();
Thread test1=new Thread(new Runnable() {
@Override
public void run() {
while(true) {
aProducer.produce();
}
}
},"test1");
Thread test2=new Thread(new Runnable() {
@Override
public void run() {
while(true) {
aProducer.customer();
}
}
},"test2");
test1.start();
test2.start();
//bProducer.start();
}
}
生产者生产:1,还剩下:1
消费者消费:1,还剩下:0
消费者消费:0,储量不足
生产者生产:1,还剩下:1
生产者生产:1,还剩下:2
生产者生产:1,还剩下:3
生产者生产:1,还剩下:4
消费者消费:1,还剩下:3
生产者生产:1,还剩下:4
生产者生产:1,还剩下:5
生产者生产:1,还剩下:6
消费者消费:1,还剩下:5
消费者消费:1,还剩下:4
消费者消费:1,还剩下:3
生产者生产:1,还剩下:4
生产者生产:1,还剩下:5
生产者生产:1,还剩下:6
生产者生产:1,还剩下:7