同步多线程:当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行,另一个必须等待当前线程执行完这个代码块以后才能执行改代码。
class Task{
public int i = 0;
public synchronized void changeI(){
System.out.println("begin task");
for(int j = 0; j < 5; j++){
System.out.print(i + "--" + Thread.currentThread().getName()+" ");
i++;
}
System.out.println("\nend task");
}
}
class ThreadA extends Thread{
Task task;
public ThreadA(Task task) {
// TODO Auto-generated constructor stub
this.task = task;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
task.changeI();
}
}
客户端执行类
public class SyschronizedTest {
public static void main(String[] args){
Task task = new Task();
ThreadA a = new ThreadA(task);
ThreadA b = new ThreadA(task);
a.start();
b.start();
}
}
运行结果
用同步代码块解决同步方法的弊端
class TaskProblem{
private String getData1;
private String getData2;
public void doLongTimeTask() throws InterruptedException{
System.out.println("begin task");
Thread.sleep(3000);
String PrivateGetData1 = "长时间处理任务后从远程返回到的值1 threadName = " + Thread.currentThread().getName();
String PrivateGetData2 = "长时间处理任务后从远程返回到的值2 threadName = " + Thread.currentThread().getName();
synchronized(this){
getData1 = PrivateGetData1;
getData2 = PrivateGetData2;
}
System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
}
}
class ThreadProblem extends Thread{
TaskProblem task;
public ThreadProblem(TaskProblem task) {
// TODO Auto-generated constructor stub
this.task = task;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
task.doLongTimeTask();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class SynchronizedTestProblem {
public static void main(String[] args){
TaskProblem task = new TaskProblem();
ThreadProblem a = new ThreadProblem(task);
ThreadProblem b = new ThreadProblem(task);
a.start();
b.start();
}
}
第一次运行:
第二次运行:
总结:当一个线程访问Object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象的非synchronized(this)同步代码块。
一半异步,一半同步
下面这个程序用来说明:不在synchronized块中就是异步执行,在synchronized块中的就是同步执行
class TaskAsync{
public void doLongTimeTask(){
for(int i = 0; i < 5; i++){
System.out.println("nosynchronized threadName = " + Thread.currentThread().getName() + " i=" + (i+1));
}
System.out.println("");
synchronized (this) {
for(int i = 0;i < 5; i++){
System.out.println("synchronized threadName=" + Thread.currentThread().getName() + " i=" + (i+1));
}
}
}
}
class ThreadAsync extends Thread{
TaskAsync task;
public ThreadAsync(TaskAsync task) {
// TODO Auto-generated constructor stub
this.task = task;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
task.doLongTimeTask();
}
}
public class SynchronizedTestAsync {
public static void main(String[] args){
TaskAsync task = new TaskAsync();
ThreadAsync a = new ThreadAsync(task);
ThreadAsync b = new ThreadAsync(task);
a.start();
b.start();
}
}
运行结果:
synchronized代码块之间的同步性
在使用同步synchronized(this)代码块时需要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问将被阻塞,这说明synchronized使用的“对象监视器”是一个。
class ObjectService{
public void serviceMethodA() throws InterruptedException{
synchronized(this){
System.out.println("A begin time=" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("A end end=" + System.currentTimeMillis());
}
}
public void serviceMethodB(){
synchronized(this){
System.out.println("B begin time=" + System.currentTimeMillis());
System.out.println("B end time=" + System.currentTimeMillis());
}
}
}
class ThreadObjectA extends Thread{
private ObjectService service;
public ThreadObjectA(ObjectService service) {
// TODO Auto-generated constructor stub
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
service.serviceMethodA();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ThreadObjectB extends Thread{
private ObjectService service;
public ThreadObjectB(ObjectService service) {
// TODO Auto-generated constructor stub
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
service.serviceMethodB();
}
}
运行结果
验证同步synchronized(this)代码块是锁定当前对象的
和synchronized方法一样,synchronized(this)代码块也是锁定当前对象的。