Upload
carla-wynn
View
25
Download
1
Embed Size (px)
DESCRIPTION
A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs. Bart Jacobs 1 (≠ Prof. B. P. F. Jacobs, R.U.Nijmegen, The Netherlands) Joint work with Jan Smans 1 , Frank Piessens 1 , Wolfram Schulte 2 , Rustan Leino 2 1 K.U.Leuven, Belgium - PowerPoint PPT Presentation
Citation preview
A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs
Bart Jacobs1 (≠ Prof. B. P. F. Jacobs, R.U.Nijmegen, The Netherlands)
Joint work with Jan Smans1, Frank Piessens1, Wolfram Schulte2 , Rustan Leino2
1 K.U.Leuven, Belgium
2 Microsoft Research, Redmond, WA, USA
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
The Problem
Goal: Delivering correct concurrent Java programs
Problem: It’s hard to reason about such programs due to the non-local nature of data races, deadlocks, and object
aliasing
Proposed solution: A programming regime (or programming model)
that prevents data races and deadlocks, and enables local reasoning in the presence of object aliasing.
An annotation syntax and verification approach that enables modular static verification of compliance with the
programming model.
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
Data Races
class Account { int balance; }
Account act = …;
int b0 = act.balance;
act.balance += 50;
int b1 = act.balance;
b1 == b0 + 50? Not necessarily!
Data Races
class Account { int balance; }
Account act = …; int b0, b1;
synchronized (act) {
b0 = act.balance;
act.balance += 50;
b1 = act.balance;
}
b1 == b0 + 50? Not necessarily!
Data Races
class Account { int balance; }
Account act = …; int b0, b1;
synchronized (act) {
b0 = act.balance;
act.balance += 50;
b1 = act.balance;
}
b1 == b0 + 50? Not necessarily!
In Java, it’s not sound to reason sequentially about sequential code
due to the possibility of data races.
Preventing data races: Access sets Per-thread access set t.A
x = o.f; or o.f = x; requires o in t.A
Always: t1 != t2 ==> t1.A and t2.A disjoint
Object can move between access sets only via proper synchronization
Preventing data races: Access sets x := new C; implies x in t.A’
entering synchronized (o) implies o in t.A’
exiting synchronized (o) implies o not in t.A’
Preventing data races: Access sets x := new C; implies x in t.A’
entering synchronized (o) implies o in t.A’
exiting synchronized (o) implies o not in t.A’
But: races between creating thread and locking thread?
Preventing data races:Shared and unshared objects x := new C; implies x is unshared’
attempting synchronized (o) requires x is shared
programmer indicates share o; requires o in t.A and o is unshared implies o is not in t.A’ and o is shared’
shared objects never become unshared again
Property: If a shared object o is not locked by any thread, then it is not in any thread’s access set.
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t1.Ashared
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t1.Asharedx
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t1.Asharedx
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t1.Asharedx
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t2.A
sharedx
t1.A
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t2.A
sharedx
t1.A
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t2.A
sharedx
t1.A
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t2.A
sharedx
t1.A
Thread creation
new Thread(r).start() requires r in t.A implies r not in t.A’
in new thread: r in t.A
Preventing Data Races: Lock Re-entry Causes difficulties for method effect framing
We disallow it
Preventing data races:Modular Static Verification Annotations required:
Share commands Method contracts
requires/ensures o is in tid.A (tid = current thread) requires/ensures o is unshared/shared requires/ensures o is not in tid.lockset/tid.lockset is empty
Field modifier: shared
Verification approach: Verification condition generation On entry to synchronized block:
foreach (o.f where o not in t.A) { o.f := random; } Method effect framing: required access sets
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
main.Ashared
main
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
main
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
main
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
main
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
main
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
s1.A
main
s1
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
s2
s1.A
main
s1
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
s2
s1.A
main
s1
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s1s2
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s1s2
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s1
s2
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s2
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s2
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s2
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
Preventing deadlocks
Deadlock = cycle of threads each waiting for the next to release a lock
Proposed solution: Programmer constructs partially ordered set of lock levels
using l := between({ll1,...,lln},{lu1,...,lum}); annotation Assigns a lock level to each shared object A thread may attempt to acquire an object’s lock only if the object
is below the objects whose lock it already holds
Preventing deadlocks: exampleclass Fork {}
class Philosopher implements Runnable {
shared Fork fa, fb;
Philosopher(Fork fa, Fork fb) requires fa.locklevel < fb.locklevel;
{ this.fa = fa; this.fb = fb; }
public void run() requires this in tid.A and lockset is empty;
{ synchronized (fb) { synchronized (fa) { /* eat */ } } }
}
Fork f1 = new Fork(); locklevel l1 = between({},{}); share f1 at l1;
Fork f2 = new Fork(); locklevel l2 = between({l1},{}); share f2 at l2;
Fork f3 = new Fork(); locklevel l3 = between({l2},{}); share f3 at l3;
new Thread(new Philosopher(f1, f2)).start();
new Thread(new Philosopher(f2, f3)).start();
new Thread(new Philosopher(f1, f3)).start();
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
Rep Objects Objects often use auxiliary objects to help represent their
state e.g. an ArrayList uses an array object
We wish to protect the array object against data races using the lock of the ArrayList object
Proposed solution: use Spec#’s ownership system Fields may be marked with rep modifier The objects pointed to by o’s rep fields are its rep objects An object may be packed or unpacked When an object is in the packed state, it owns its rep objects A thread can gain access to an owned object by locking the
owner and then unpacking the owner
Ownership system
When packing an object o, using a pack o; annotation, o’s rep objects are removed from tid.A
When unpacking o, using an unpack o; annotation, o’s rep objects are added to tid.A
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
t.Ashared
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
bl
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
Object invariantsclass Account { int balance;
Account() ensures this in tid.A; {
} void deposit(int amount) requires this in tid.A && 0 <= amount; ensures this in tid.A; {
balance += amount;
}}
Account a = new Account();share a;…synchronized (a) { assert 0 <= a.balance; // does not verify}
Object invariantsclass Account { int balance; invariant 0 <= balance; Account() ensures this in tid.A && this is packed; { pack this; } void deposit(int amount) requires this in tid.A && this is packed && 0 <= amount; ensures this in tid.A && this is packed; { unpack this; balance += amount; pack this; }}
Account a = new Account();share a;…synchronized (a) { assert 0 <= a.balance; // verifies!}
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
Immutable objectsclass BoundedList {
rep Object[] elements;
int count;
ArrayList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
Object get(int index)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this; Object v = elements[index]; pack this;
return v;
}
}
class RsaServer implements Runnable {
shared BoundedList primes;
RsaServer(BoundedList primes)
requires primes is shared;
ensures this is in tid.A and this is packed;
{ this.primes = primes; pack this; }
public void run()
requires lockset is empty;
requires this is in tid.A and this is packed;
{
synchronized (primes) {
/* perform RSA operations */
… int p = primes[…]; …
}
}
}
BoundedList primes = new BoundedList();
fillWithPrimes(primes);
share primes;
new Thread(new RsaServer(primes)).start();
new Thread(new RsaServer(primes)).start();
Immutable objectsclass BoundedList {
rep Object[] elements;
int count;
ArrayList(int capacity)
ensures this is in tid.W and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.W and this is packed;
ensures this is in tid.W and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
Object get(int index)
requires this is in tid.R and this is packed;
{
read (this) { return elements[index]; }
}
}
class RsaServer implements Runnable {
shared_immutable BoundedList primes;
RsaServer(BoundedList primes)
requires primes is shared_immutable;
ensures this is in tid.W and this is packed;
{ this.primes = primes; pack this; }
public void run()
requires lockset is empty;
requires this is in tid.W and this is packed;
{
/* perform RSA operations */
… int p = primes[…]; …
}
}
BoundedList primes = new BoundedList();
fillWithPrimes(primes);
share_immutable primes;
new Thread(new RsaServer(primes)).start();
new Thread(new RsaServer(primes)).start();
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
Related Work
ESC/Modula3, ESC/Java, RCC/Java Calvin/R Safe Concurrent Java Atomicity JML Separation logic Monitor invariants Assertional proof system for monitors Dynamic tools: Eraser, RaceTrack Software Transactional Memory
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
Future work
Integrating support for module invariants and rely-guarantee conditions
Verification of non-blocking algorithms (volatile, CAS)
Verification of additional liveness properties
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
Conclusion
Programming model and static verification approach
that prevents data races and deadlocks
and supports local reasoning in the presence of object aliasing, using an ownership system.
Has support for object invariants immutable objects
A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs
Bart Jacobs1
Joint work with Jan Smans1, Frank Piessens1, Wolfram Schulte2 , Rustan Leino2
1 K.U.Leuven, Belgium
2 Microsoft Research, Redmond, WA, USA