package Synchronize;
/**
* 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。
* 另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块
* */
public class Test01 implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop:: " + i);
}//这个部分可能是A0 B0等间隔出现
synchronized(this){//对象锁 一个时间段里面只有一个对象实例才能访问 且必须要等其执行完代码块
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}//但是这个部分输出都是连续的
}
public static void main(String[] args) {
Test01 t1 = new Test01();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start(); //不一定就一定是先输出A
tb.start();
}
}
/*
A synchronized loop:: 0
B synchronized loop:: 0
A synchronized loop:: 1
B synchronized loop:: 1
A synchronized loop:: 2
B synchronized loop:: 2
A synchronized loop:: 3
A synchronized loop:: 4
A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop:: 3
B synchronized loop:: 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
* */
package Synchronize;
/**
* 一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块
* */
public class Test02 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " :: " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
Test02 myt2 = new Test02();
Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); myt2.m4t2(); } }, "t1" );
Thread t2 = new Thread( new Runnable() { public void run() { myt2.m4t1();myt2.m4t2(); } }, "t2" );
//刚开始的时候 两个线程都想访问m4t1 但是只能有一个去访问 当t1线程去访问非同步方法的时候,t2就去访问其同步方法
t1.start();
t2.start();
}
}
package Synchronize;
/**
* 当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问是阻塞的
* */
public class Test03 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t3() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public static void main(String[] args) {
Test03 myt2 = new Test03();
Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); } }, "t1" );
Thread t2 = new Thread( new Runnable() { public void run() { myt2.m4t2(); } }, "t2" );
Thread t3 = new Thread( new Runnable() { public void run() { myt2.m4t3(); } }, "t3" );
t1.start();
t2.start();
t3.start();
}
}
/*
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
t3 : 4
t3 : 3
t3 : 2
t3 : 1
t3 : 0
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
* */
package Synchronize;
/**
* 当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。
* 结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞
* */
public class Test04 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public synchronized void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
Test04 myt4 = new Test04();
Thread t1 = new Thread( new Runnable() { public void run() { myt4.m4t1(); } }, "t1" );
Thread t2 = new Thread( new Runnable() { public void run() { myt4.m4t2(); } }, "t2" );
t1.start();
t2.start();
}
}
package Synchronize;
public class Test05 {
class Inner {
private void m4t1() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //使用对象锁
inner.m4t1();
}
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Test05 myt3 = new Test05();
final Inner inner = myt3.new Inner();//普通内部类
Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");
Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");
t1.start();
t2.start();
}
}
/*
尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=0
* */
package Synchronize;
public class Test06 {
class Inner {
private void m4t1() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private synchronized void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //使用对象锁
inner.m4t1();
}
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Test06 myt3 = new Test06();
final Inner inner = myt3.new Inner();//普通内部类
Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");
Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");
t1.start();
t2.start();
}
}
/*
加在内部类里面的方法
t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0
* */
package Synchronize;
public class Test07 {
class Inner {
private void m4t1() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //使用对象锁
inner.m4t1();
}
}
private synchronized void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Test07 myt3 = new Test07();
final Inner inner = myt3.new Inner();//普通内部类
Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");
Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");
t1.start();
t2.start();
}
}
/*
按照Test04的理解是应该先输完某一个再输另外一个的 但是实际的结果交错的
再结合Test06 其实调用方法的时候还是要去看其最底层是不是同步的
加在内部类外面的方法
t1 : Inner.m4t1()=4
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=2
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0
t1 : Inner.m4t1()=0
* */
三句话:
第一,同步代码块或者同步方法体和非同步一起,两个线程可以一起访问非,但是只能先后顺序访问同
第二,访问一个同将导致其他同阻塞 但是不会阻塞非同
第三,是否真正同步需要看最底层(内部类)
但是需要注意的是上面都是不同线程 同一个对象,如果是不同的对象呢?
package Synchronize;
public class Test031 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t3() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
Test031 myt2 = new Test031();
Test031 myt3 = new Test031();//隶属于两个不同的对象锁,所以是可以交替进行的 前面我们所讲都是不同线程 同一个对象
Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); } }, "t1" );
Thread t2 = new Thread( new Runnable() { public void run() { myt3.m4t1(); } }, "t2" );
t1.start();
t2.start();
}
}
/*
t2 : 4
t1 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t2 : 1
t1 : 1
t2 : 0
t1 : 0
* */
不同的实例对象拥有不同的锁,因此互不干扰
java的对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的
package Synchronize;
/**
* 类锁和对象锁是两个不一样的锁,控制着不同的区域,它们是互不干扰的。
* 同样,线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁,这是允许的。
*/
public class Test033 {
public synchronized void test1()
{
int i = 5;
while( i-- > 0)
{
System.out.println(Thread.currentThread().getName() + " : " + i);
try
{
Thread.sleep(500);
}
catch (InterruptedException ie)
{
}
}
}
public static synchronized void test2()
{
int i = 5;
while( i-- > 0)
{
System.out.println(Thread.currentThread().getName() + " : " + i);
try
{
Thread.sleep(500);
}
catch (InterruptedException ie)
{
}
}
}
public static void main(String[] args)
{
final Test033 myt2 = new Test033();
Thread test1 = new Thread( new Runnable() { public void run() { myt2.test1(); } }, "test1" );
Thread test2 = new Thread( new Runnable() { public void run() { Test033.test2(); } }, "test2" );
test1.start();
test2.start();
}
}
/*
test1 : 4
test2 : 4
test1 : 3
test2 : 3
test1 : 2
test2 : 2
test1 : 1
test2 : 1
test1 : 0
test2 : 0
* */
package Synchronize;
/**
* 类锁 同一时间内只有一个类实例可以获得
* */
public class Test032 {
public void test1()
{
synchronized(Test032.class)//类锁
{
int i = 5;
while( i-- > 0)
{
System.out.println(Thread.currentThread().getName() + " : " + i);
try
{
Thread.sleep(500);
}
catch (InterruptedException ie)
{
}
}
}
}
public static synchronized void test2() //静态方法的类锁
{
int i = 5;
while( i-- > 0)
{
System.out.println(Thread.currentThread().getName() + " : " + i);
try
{
Thread.sleep(500);
}
catch (InterruptedException ie)
{
}
}
}
public static void main(String[] args)
{
final Test032 myt2 = new Test032();
Thread test1 = new Thread( new Runnable() { public void run() { myt2.test1(); } }, "test1" );
Thread test2 = new Thread( new Runnable() { public void run() { Test032.test2(); } }, "test2" );
test1.start();
test2.start();
}
}
/*
test1 : 4
test1 : 3
test1 : 2
test1 : 1
test1 : 0
test2 : 4
test2 : 3
test2 : 2
test2 : 1
test2 : 0
* */
参考文章:
http://langgufu.iteye.com/blog/2152608
http://www.importnew.com/20444.html
http://liuinsect.iteye.com/blog/1662839