还可以作用于静态方法,类和某个实例。
synchronized分为代码块和方法,代码块需要显示的指定对象,而方法不需要(即当前对象)。
java的内存模型是对每一个进程都有主内存,每个线程也有自己的内存,它们从主内存中取数据,然后在计算,在存入主内存。
例子:现在有两个线程A,B线程,A线程对变量i加1,B线程同时对i加2,这两个线程同时操作,如果没有同步处理则B线程做的操作会覆盖A线程的操作。
synchronized具有原子性,原子操作:取数据,操作数据,存数据。synchronized可以保证同一时间只有一个线程操作该对象。
java中对非Long和Float原始数据类型的存,取为原子操作。其实就是对一个字节的存,取操作,由于Float和Long为两个字节,所以其取,存为非原子操作。如果想把他们变成原子操作可以用volatile.
作用区域主要有两种:
(1)、方法
(2)、代码块
对于用一对像的同步操作只能有一个线程,而对于不同对象是互不干扰的。
Public synchronized void change() {
//同步方法
}
Public void change() {
Synchronized(this) {
//同步语句:(因为效率问题,有时考虑使用同步语句块)
}
}
Public synchronized void change() {
//同步方法
}
Public void change() {
Synchronized(this) {
//同步语句:(因为效率问题,有时考虑使用同步语句块)
}
}
同步方法是针对当前对象的,如果不针对当前对象,而是针对其他对象可以用同步语句,如:
private byte[] lock= new byte[0];
Public void change() {
Synchronized(lock) {
}
}
private byte[] lock= new byte[0];
Public void change() {
Synchronized(lock) {
}
}
自定义锁注意:
a、对象必须为private防止其他类对象访问
b、geter方法最好clone一个对象返回
其他用法
可以针对静态方法和类
Class Foo {
public synchronizedstatic void methodAAA()// 同步的static 函数
{
//….
}
public void methodBBB() {
synchronized(Foo.class)
// class literal(类名称字面常量)
}
}
Class Foo {
public synchronizedstatic void methodAAA()// 同步的static 函数
{
//….
}
public void methodBBB() {
synchronized(Foo.class)
// class literal(类名称字面常量)
}
}
它是针对整个类的,所以只能是同一个类的一个线程进行访问
synchronized(static class)的区别:
synchronized就是针对内存区块申请内存锁,this是类的一个对象,也就是针对相同对象的互斥操作,其他线程可以访问该类的其他对象。static是针对类,static是整个类共有的,也就是该类的所有成员间互斥。在同一时间只有一个线程可以访问该类的实例。
建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。代码如下:
public class MyThreadPrinter2 implements Runnable {
private String name;
private Object prev;
private Object self;
private MyThreadPrinter2(String name, Object prev, Object self) {
this.name = name;
this.prev = prev;
this.self = self;
}
@Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
count--;
self.notify();
}
try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);
MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);
MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);
new Thread(pa).start();
new Thread(pb).start();
new Thread(pc).start(); }
}
public class MyThreadPrinter2 implements Runnable {
private String name;
private Object prev;
private Object self;
private MyThreadPrinter2(String name, Object prev, Object self) {
this.name = name;
this.prev = prev;
this.self = self;
}
@Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
count--;
self.notify();
}
try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);
MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);
MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);
new Thread(pa).start();
new Thread(pb).start();
new Thread(pc).start(); }
}