您的位置:首页 > 编程语言 > Java开发

java之关键字synchronized

2016-03-11 14:52 246 查看
synchronized介绍

java的关键字synchronized是在java的多线程中应用到的.可以用来给程序的方法或者是代码块进行加锁,保证单一时间段内的做多只能有一个线程执行这段加锁的代码.将其比作钥匙,房子,屏风的关系更容易理解,简单概括,多个线程用多个人代表,不同的对象用不同的房子代表,不同的代码块用屏风来代表,synchronized修饰的对象为上锁的房子,synchronized修饰的代码块代表着上锁的屏风.每个人用到的房子时候会带走其中的钥匙,当程序走到sleep()函数的时候,只代表进入其中的人没出来休息一下会继续他的工作.每个人走到房子前会看看是否被synchronized修饰,也就是是否上锁了,没有的话就会执行相关的程序代码,发现钥匙不在,则会一直等待.

sychronized使用方式

修饰方法

public synchronized void innerTest1(InnerTest inner) {
...
}
对相关的方法进行加锁,线程唯一使用该方法,当方法执行结束后其他的进程才能调用该方法.

修饰程序块

synchronized (String val) {
...
}

修饰对象

synchronized (Object objct) {
...
}
代码示例

方式一:

package com.threadTest;
public class TestThread3 {
public class InnerTest {
public void t3() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "Inner " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void t4() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "Inner " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public synchronized void innerTest1(InnerTest inner) {
//        synchronized (inner) {
inner.t3();
//        }
}

public void innerTest2(InnerTest inner) {
synchronized (inner) {
inner.t4();
}
}

}

主函数测试

import com.threadTest.TestThread;
import com.threadTest.TestThread2;
import com.threadTest.TestThread3;

public class Main {
public static void main(String[] args) {
final TestThread3 testThread3 = new TestThread3();
final TestThread3.InnerTest innerTest = testThread3.new InnerTest();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
testThread3.innerTest1(innerTest);
}
}, "thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
testThread3.innerTest2(innerTest);
}
}, "thread2");

thread.start();
thread2.start();
}
}
方式二:

package com.threadTest;
public class TestThread2 {
public void t1() {
synchronized (this) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "   " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public void t2() {
synchronized (this) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " $ " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
主函数测试:

import com.threadTest.TestThread2;

public class Main {

public static void main(String[] args) {
final TestThread2 testThread2 = new TestThread2();
Thread test1 = new Thread(new Runnable() {
@Override
public void run() {
testThread2.t1();
}
} , "thread 2");

Thread test2 = new Thread(new Runnable() {
@Override
public void run() {
testThread2.t2();
}
}, "thread 1");

test1.start();
test2.start();
}
}
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

六、在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: