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

java学习(synchronized)

2016-12-10 22:52 267 查看

synchronized关键字

作用:

1. 修饰代码块,被修饰的代码块称为同步语句块,其作用范围是{}括起来的代码,作用的对象是调用这个代码块的对象

2. 修饰非静态方法,被修饰的方法称为同步方法,其作用范围是整个方法,作用的对象是调用这个方法的对象

3. 修饰静态方法,其作用范围是整个静态方法,作用的对象是这个类所有的对象

4. 修饰类,其作用的范围是synchronized后面括起来的部分,作用的对象是这个类的所有对象

对代码块加锁

代码

public class ThreadSynchronize implements Runnable {
public void run() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "synchronized loop" + i);
}

}
}

public static void main(String[] args) {
ThreadSynchronize t1 = new ThreadSynchronize();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();

}
}


结果

Asynchronized loop0
Asynchronized loop1
Asynchronized loop2
Asynchronized loop3
Asynchronized loop4
Bsynchronized loop0
Bsynchronized loop1
Bsynchronized loop2
Bsynchronized loop3
Bsynchronized loop4


由代码可以得出结论:当两个并发进程访问同一个对象的由synchronized (this)修饰地代码块时,一次只能有一个线程得到这个代码块,另一个必须等待

注意:是两个线程访问同一个对象的,同一个对象的,同一个对象的!

将main函数改为如下如下代码:

ThreadSynchronize t1 = new ThreadSynchronize();
ThreadSynchronize t2 = new ThreadSynchronize();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t2, "B");
ta.start();
tb.start();


得到结果

Asynchronized loop0
Bsynchronized loop0
Asynchronized loop1
Bsynchronized loop1
Asynchronized loop2
Asynchronized loop3
Bsynchronized loop2
Asynchronized loop4
Bsynchronized loop3
Bsynchronized loop4


也就是说,当不同线程要访问不同对象的同一个代码块时,synchronized不会起到阻塞效果

代码

public class ThreadSynchronize {
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) {
ThreadSynchronize t1 = new ThreadSynchronize();
Thread ta = new Thread(new Runnable() {
@Override
public void run() {
t1.m4t1();
}
},"ta");
Thread tb = new Thread(new Runnable() {
@Override
public void run() {
t1.m4t2();
}
},"tb");
ta.start();
tb.start();

}
}


结果

tb: 4
ta: 4
tb: 3
ta: 3
ta: 2
tb: 2
ta: 1
tb: 1
tb: 0
ta: 0


结果表明:当一个线程访问一个对象的synchronized(this) 代码块时,另一个线程可以访问该对象的非synchronized(this) 修饰的代码块(不同函数中的)

将m4t2()修改得与m4t1()相同,即都用synchronized(this)修饰后,得到结果

ta: 4
ta: 3
ta: 2
ta: 1
ta: 0
tb: 4
tb: 3
tb: 2
tb: 1
tb: 0


结果表明:当一个线程访问到了一个对象的synchronized(this)修饰的代码块时,其他所有线程对该对象的synchronized(this)修饰的代码块的访问都会被阻塞,此时称该线程获取了该对象的对象锁,使得其他线程都不能在此时访问同步代码块

对指定某个对象加锁

public class ThreadSynchronize {
public static void main(String[] args) {
Account account = new Account("zhangsan", 10000);
AccountOperator accountOperator = new AccountOperator(account);

final int THREAD_NUM = 5;
Thread[] threads = new Thread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++) {
threads[i] = new Thread(accountOperator, "Thread" + i);
threads[i].start();
}
}
}

class Account {
String name;
float amount;

public Account(String name, float amount) {
this.name = name;
this.amount = amount;
}

public void deposit(float amt) {
amount += amt;
try{
Thread.sleep(100);
} catch (InterruptedException e){

}
}
public void withdraw(float amt) {
amount -= amt;
try {
Thread.sleep(100);
} catch(InterruptedException e){

}
}

public float get() {
return amount;
}
}

class AccountOperator implements Runnable {
private Account account;
public AccountOperator(Account account) {
this.account = account;
}

@Override
public void run() {
// TODO Auto-generated method stub
synchronized(account){
account.deposit(500);
account.withdraw(300);
System.out.println(Thread.currentThread().getName() + " : " + account.get());
}
}

}


输出结果

Thread0 : 10200.0
Thread3 : 10400.0
Thread4 : 10600.0
Thread2 : 10800.0
Thread1 : 11000.0


在run方法里,我们用synchronized给account对象加了锁,此时,其他想要访问也对account加了锁的区域的线程将会被阻塞

修饰一个非静态方法

public synchronized void run() {
// TODO Auto-generated method stub

account.deposit(500);
account.withdraw(300);
System.out.println(Thread.currentThread().getName() + " : " + account.get());

}


表示该方法一次只能让一个对象调用,与之前一个表示方式等价

修饰静态方法

很明显,静态方法是属于类的,因此,静态方法可以保证同一个类的不同实例之间保持同步

public class ThreadSynchronize implements Runnable {
public void run() {
method();
}

public static synchronized void method(){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "synchronized loop" + i);
}
}

public static void main(String[] args) {
ThreadSynchronize t1 = new ThreadSynchronize();
ThreadSynchronize t2 = new ThreadSynchronize();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t2, "B");
ta.start();
tb.start();

}
}


输出结果为

Asynchronized loop0
Asynchronized loop1
Asynchronized loop2
Asynchronized loop3
Asynchronized loop4
Bsynchronized loop0
Bsynchronized loop1
Bsynchronized loop2
Bsynchronized loop3
Bsynchronized loop4


修饰一个类

很明显,修饰一个类的时候,该类的所有实例公用同一把锁

参考:http://blog.csdn.net/luoweifu/article/details/46613015
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java