synchronized可以加在方法体上,也可以使用在对象上
try {
synchronized (list) {
if(list.getSize() < 1){
Thread.sleep(2000);
list.add(data);
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
public synchronized void method() {
try {
System.out.println("B:" + Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("end B");
}catch (Exception e) {
e.printStackTrace();
}
}
这种同步的锁必须是要在多线程访问同一个对象实例的时候才有用,否则访问的是不同的实例对象那就一点用也没,还浪费了效率
与synchronized对应的最简单的场景就是脏读,显然解决该问题的最佳方式就是加入synchronized
public class PublicVar {
public String username = "A";
public String password = "AA";
public void setValue(String username, String password){
try {
this.username = username;
Thread.sleep(5000);
this.password = password;
System.out.println("setValue method thread name = " + Thread.currentThread().getName() + " username = " + username + " password = " + password );
} catch (Exception e) {
e.printStackTrace();
}
}
public void getValue() {
System.out.println("getValue method thread name = "
+ Thread.currentThread().getName() + " username = " + username
+ " password = " + password
);
}
public static void main(String[] args) {
try {
PublicVar publicVar = new PublicVar();
ThreadA threadA = new ThreadA(publicVar);
threadA.start();
threadA.sleep(200);
publicVar.getValue();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public class ThreadA extends Thread {
private PublicVar publicVar;
public ThreadA(PublicVar publicVar){
super();
this.publicVar = publicVar;
}
public void run(){
super.run();
publicVar.setValue("B", "BB");
}
}
接下来介绍volatile
public class RunThread extends Thread {
/**
* volatile的主要作用就是当线程访问isRuning这个变量时强制从公共堆栈中取值(当加上该修饰符该值就会被强制弄到主内存中)
* 使用volatile增加了实例变量在多个线程之间的可见性,但其关键字最致命的缺点是不支持原子性
*/
volatile private boolean isRunning = true;
public boolean isRunning() {
return isRunning;
}
public void setRunning(boolean running) {
isRunning = running;
}
@Override
public void run() {
System.out.println("run method");
while (isRunning == true) {
}
System.out.println("run method end");
}
public static void main(String[] args) {
try {
RunThread run = new RunThread();
run.start();
Thread.sleep(1000);
run.setRunning(false);
}catch (Exception e) {
e.printStackTrace();
}
}
}
volatile的主要作用就是当线程访问isRuning这个变量时强制从公共堆栈中取值(当加上该修饰符该值就会被强制弄到主内存中),使用volatile增加了实例变量在多个线程之间的可见性,但其关键字最致命的缺点是不支持原子性。
volatile与sync的区别:
1、volatile是线程同步的轻量级实现,所以volatile性能比synchronized要好,并且volatile只能修饰变量,sync能修饰方法和代码块。
2、多线程访问volatile不会发生阻塞,而sync会
3、volatile能保证数据的可见性,而不能保证原子性,而sync可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据做同步
4、volatile解决的是变量在多个线程之间的可见性,而sync解决的是多个线程之间访问资源的同步性。