两个线程均调用共享对象的同步方法:
class MyObject{
public synchronized void methodA(){
System.out.println("begin methodA threadName= " + Thread.currentThread().getName());
try {
Thread.sleep(5000);
System.out.println("methodA end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadA extends Thread{
private MyObject object;
public ThreadA(MyObject object){
this.object = object;
}
@Override
public void run() {
object.methodA();
}
}
class ThreadB extends Thread{
private MyObject object;
public ThreadB(MyObject object){
this.object = object;
}
@Override
public void run() {
object.methodA();
}
}
public class Run {
public static void main(String[] args) {
MyObject object = new MyObject();
ThreadA a = new ThreadA(object);
a.setName("A");
ThreadB b = new ThreadB(object);
b.setName("B");
a.start();
b.start();
}
}
结果肯定是顺序执行:
begin methodA threadName= A
methodA end
begin methodA threadName= B
methodA end
A线程调用共享对象的同步方法,B线程调用共享对象非同步方法:
class MyObject{
public synchronized void methodA(){
System.out.println("begin methodA threadName= " + Thread.currentThread().getName());
try {
Thread.sleep(5000);
System.out.println("methodA end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void methodB(){
System.out.println("begin methodB threadName= " + Thread.currentThread().getName());
try {
Thread.sleep(5000);
System.out.println("methodB end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadA extends Thread{
private MyObject object;
public ThreadA(MyObject object){
this.object = object;
}
@Override
public void run() {
object.methodA();
}
}
class ThreadB extends Thread{
private MyObject object;
public ThreadB(MyObject object){
this.object = object;
}
@Override
public void run() {
object.methodB();
}
}
public class Run {
public static void main(String[] args) {
MyObject object = new MyObject();
ThreadA a = new ThreadA(object);
a.setName("A");
ThreadB b = new ThreadB(object);
b.setName("B");
a.start();
b.start();
}
}
结果是:
begin methodA threadName= A
begin methodB threadName= B
methodA end
methodB end
A线程调用共享对象的同步方法,B线程调用共享对象另一个同步方法
class MyObject{
public synchronized void methodA(){
System.out.println("begin methodA threadName= " + Thread.currentThread().getName());
try {
Thread.sleep(5000);
System.out.println("methodA end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void methodB(){
System.out.println("begin methodB threadName= " + Thread.currentThread().getName());
try {
Thread.sleep(5000);
System.out.println("methodB end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadA extends Thread{
private MyObject object;
public ThreadA(MyObject object){
this.object = object;
}
@Override
public void run() {
object.methodA();
}
}
class ThreadB extends Thread{
private MyObject object;
public ThreadB(MyObject object){
this.object = object;
}
@Override
public void run() {
object.methodB();
}
}
public class Run {
public static void main(String[] args) {
MyObject object = new MyObject();
ThreadA a = new ThreadA(object);
a.setName("A");
ThreadB b = new ThreadB(object);
b.setName("B");
a.start();
b.start();
}
}
结果是:
begin methodA threadName= A
methodA end
begin methodB threadName= B
methodB end
结论:
1. A线程和B线程均调用object对象的synchronized方法,则必须是同步方式调用
2. A线程先持有object对象的Lock锁,B线程可以以异步方式调用object对象中的非synchronized类型的方法
3. A线程先持有object对象的Lock锁,B线程如果此时调用object对象中的synchronized类型的方法则需等待,即只能是同步方式调用
结论2即对应了脏读的现象:
比如赋值方法是同步,取值方法是非同步,则可能出现脏读,即在读取实例变量时,此值已经被其他线程更改过了
class MyObject{
private String username = "A";
private String password = "AA";
public synchronized void setValue(String username, String password){
this.username = username;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.password = password;
System.out.println("setValue username : " + username + " password : " + password);
}
public void getValue(){
System.out.println("getValue username : " + username + " password : " + password);
}
}
class ThreadA extends Thread{
private MyObject object;
public ThreadA(MyObject object){
this.object = object;
}
@Override
public void run() {
object.setValue("B", "BB");
}
}
public class Run {
public static void main(String[] args) {
MyObject object = new MyObject();
ThreadA a = new ThreadA(object);
a.setName("A");
a.start();
try {
Thread.sleep(200);//结果受此值影响
} catch (InterruptedException e) {
e.printStackTrace();
}
object.getValue();
}
}
可对getValue添加synchronzied关键字修饰,避免脏读
当线程调用anyObject对象加入synchronized关键字修饰的X方法时,A线程就获得了X方法锁,更准确的讲是获得了anyObject对象的锁,所以其他线程必须等A线程执行完毕才可以调用X方法,但是其他线程可以调用anyObject的其他非synchronized关键字修饰的方法。可若其他线程调用anyOjbect的其他synchronized关键字修饰的方法时,也必须等待A线程执行完毕,释放了对象锁后才可以调用