diff --git a/exercises/approximate-counter/Makefile b/exercises/approximate-counter/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1982557b80603af6bd06b9bc5fe7e9925fad3235
--- /dev/null
+++ b/exercises/approximate-counter/Makefile
@@ -0,0 +1,19 @@
+PROG = main
+OBJECTS = main.o counter.o
+CC = gcc
+CFLAGS = -Wall -std=c99 -pthread
+CFLAGS += -I. # add the current directory to the include path
+
+.Phone: all
+all: clean $(PROG) # build and run the program
+	./$(PROG)
+
+$(PROG): $(OBJECTS) # link the object files into a binary
+	$(CC) $(CFLAGS) $^ -o $@
+
+$(OBJECTS): %.o: %.c counter.h # compile the source files into object files
+	$(CC) $(CFLAGS) -c $<
+
+.PHONY: clean
+clean: # remove the object files and the binary
+	rm -f $(OBJECTS) $(PROG)
diff --git a/exercises/approximate-counter/counter.c b/exercises/approximate-counter/counter.c
index 24ab997329acf6550b1599228a19382f5db7e45b..7f6d0ee770b2b97dd1cafb1ab0160bc232091825 100644
--- a/exercises/approximate-counter/counter.c
+++ b/exercises/approximate-counter/counter.c
@@ -1,24 +1,58 @@
 #include "counter.h"
 
 void init_counter(counter_t *c, int threshold, int num_cpu) {
-  // TODO: Implement this function
+  c->num_cpu = num_cpu;
+  c->threshold = threshold;
+  c->global = 0;
+  c->local = malloc(num_cpu * sizeof(long));
+  c->llock = malloc(num_cpu * sizeof(pthread_mutex_t));
+  pthread_mutex_init(&c->glock, NULL);
+  int i;
+  for (i = 0; i < num_cpu; i++) {
+    c->local[i] = 0;
+    pthread_mutex_init(&c->llock[i], NULL);
+  }
 }
 
-void update_counter(counter_t *c, int t_id, int amount) {
-  // TODO: Implement this function
+void update_counter(counter_t * c, int t_id, int amount) {
+int cpu = t_id % c->num_cpu;
+    pthread_mutex_lock(&c->llock[cpu]);
+    c->local[cpu] += amount;
+    if (c->local[cpu] >= c->threshold) {
+        pthread_mutex_lock(&c->glock);
+        c->global += c->local[cpu];
+        pthread_mutex_unlock(&c->glock);
+        c->local[cpu] = 0;
+    }
+    pthread_mutex_unlock(&c->llock[cpu]);
 }
 
 int get_counter_val(counter_t *c) {
-  pthread_mutex_lock(&c->glock);
-  int val = c->global;
-  pthread_mutex_unlock(&c->glock);
-  return val;
+    pthread_mutex_lock(&c->glock);
+    int val = c->global;
+    pthread_mutex_unlock(&c->glock);
+    return val;
 }
 
 void sync_counter(counter_t *c) {
-  // TODO: Implement this function
+    int i;
+    for (i = 0; i < c->num_cpu; i++) {
+        pthread_mutex_lock(&c->llock[i]);
+        pthread_mutex_lock(&c->glock);
+        c->global += c->local[i];
+        pthread_mutex_unlock(&c->glock);
+        c->local[i] = 0;
+        pthread_mutex_unlock(&c->llock[i]);
+    }
+
 }
 
 void destroy_counter(counter_t *c) {
-  // TODO: Implement this function
+    pthread_mutex_destroy(&c->glock);
+    int i;
+    for (i = 0; i < c->num_cpu; i++) {
+        pthread_mutex_destroy(&c->llock[i]);
+    }
+    free(c->local);
+    free(c->llock);
 }